From: Fabian on
Hello,

last week I got the suggestion to write template functions for my error
handling. With the implementation I've got a little problem: As the functions
are in a separate dll, I have to instantiate them explicitely in the cpp
file. This works fine for parameters of type int or double. The main purpose
of my error printing function is to print a message though. But for a
explicit instantiation with a char* parameter, the linker strikes:

// header file:
template <typename T1> void TEMPLDLL_API PrintError(const T1& arg1);

// cpp file:
template <typename T1> void PrintError(const T1& arg1)
{
cerr << arg1 << endl;
}

// function call:
PrintError("There was an error.");

This causes a LNK2019:

error LNK2019: unresolved external symbol "__declspec(dllimport) void
__cdecl PrintError<char const [20]>(char const (&)[20])" ...

If I now cast the string to a char* the error is
gone: ErrorHandling::PrintError((char*)"There was an error."); // works

This is really ugly though esp. for an overload with several parameters.
More than ever if I do it the clean c++ way with static_cast<char*>("There
was an error");.

Any suggstions?

Thanks in advance,

Fabian
From: Alf P. Steinbach on
* Fabian:
>
> last week I got the suggestion to write template functions for my error
> handling. With the implementation I've got a little problem: As the functions
> are in a separate dll, I have to instantiate them explicitely in the cpp
> file. This works fine for parameters of type int or double. The main purpose
> of my error printing function is to print a message though. But for a
> explicit instantiation with a char* parameter, the linker strikes:
>
> // header file:
> template <typename T1> void TEMPLDLL_API PrintError(const T1& arg1);
>
> // cpp file:
> template <typename T1> void PrintError(const T1& arg1)
> {
> cerr << arg1 << endl;
> }
>
> // function call:
> PrintError("There was an error.");
>
> This causes a LNK2019:
>
> error LNK2019: unresolved external symbol "__declspec(dllimport) void
> __cdecl PrintError<char const [20]>(char const (&)[20])" ...
>
> If I now cast the string to a char* the error is
> gone: ErrorHandling::PrintError((char*)"There was an error."); // works
>
> This is really ugly though esp. for an overload with several parameters.
> More than ever if I do it the clean c++ way with static_cast<char*>("There
> was an error");.
>
> Any suggstions?

Why don't you just provide an ordinary overload for 'char const*'?


Cheers, & hth.,

- Alf


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
From: Fabian on
Hi Alf,

"Alf P. Steinbach" wrote:

> Why don't you just provide an ordinary overload for 'char const*'?

I will need overloads for at least:

(char const*)
(char const*, char const*)
(char const*, const int)
(char const*, const double)
(const int, char const*)
(char const*, char const*, char const*)
(char const*, const int, char const*)
(char const*, char const*, char const*, char const*)
(char const*, char const*, const int, char const*)
(char const*, char const*, char const*, char const*, char const*)
(char const*, char const*, char const*, const int, char const*)
(char const*, char const*, const int, char const*, char const*)
(char const*, const int, char const*, char const*, char const*)
(char const*, char const*, char const*, const double, char const*)
(char const*, char const*, const double, char const*, char const*)

And probably more. This would end in lots of double code. Do you have an
alternative idea to use templates here?

Thx,

Fabian
From: Ulrich Eckhardt on
Fabian wrote:
> last week I got the suggestion to write template functions for my error
> handling. With the implementation I've got a little problem: As the
> functions are in a separate dll, I have to instantiate them explicitely in
> the cpp file. This works fine for parameters of type int or double. The
> main purpose of my error printing function is to print a message though.

Why do you insist on having all instantiations in the DLL? Why not simply
put the non-template parts into the DLL and make the rest inline? In case
you are afraid that this will blow up the size of your executables, I'm
afraid you are optimising prematurely.

> template <typename T1> void TEMPLDLL_API PrintError(const T1& arg1);
[...]
> error LNK2019: unresolved external symbol "__declspec(dllimport) void
> __cdecl PrintError<char const [20]>(char const (&)[20])" ...
>
> If I now cast the string to a char* the error is
> gone: ErrorHandling::PrintError((char*)"There was an error."); // works
>
> This is really ugly though esp. for an overload with several parameters.
> More than ever if I do it the clean c++ way with static_cast<char*>("There
> was an error");.

Ahem, the clean C++ way would be to cast to a pointer to const char. ;)

Anyway, due to the rules of C++ template parameter deduction it picks a
reference to a const char array as parameters. However, you could also
write it this way:

PrintError<char const*>("No problem!");

i.e. explicitly set the parameters.

Uli

--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932
From: Igor Tandetnik on
"Fabian" <Fabian(a)discussions.microsoft.com> wrote in message
news:B3B2BE25-D509-432D-BEE3-146157F2AAA8(a)microsoft.com
> Hi Alf,
>
> "Alf P. Steinbach" wrote:
>
>> Why don't you just provide an ordinary overload for 'char const*'?
>
> I will need overloads for at least:
>
> (char const*)
> (char const*, char const*)
> (char const*, const int)
> (char const*, const double)
> (const int, char const*)
> (char const*, char const*, char const*)
> (char const*, const int, char const*)
> (char const*, char const*, char const*, char const*)
> (char const*, char const*, const int, char const*)
> (char const*, char const*, char const*, char const*, char const*)
> (char const*, char const*, char const*, const int, char const*)
> (char const*, char const*, const int, char const*, char const*)
> (char const*, const int, char const*, char const*, char const*)
> (char const*, char const*, char const*, const double, char const*)
> (char const*, char const*, const double, char const*, char const*)

Well, you don't seem to be deterred by the prospect of having to
explicitly instantiate and export all these specializations of your
PrintError template. Why not just define it in the header and let the
compiler produce specializations as needed?
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925