user5598651
user5598651

Reputation:

Template type deduction not working in C++

I have two templates.

The first one for an integer

template <class T>
T myMin(T a, T b)
{
    return (a < b) ? a : b;
}

The second one for a string

template <class TypeFrom, class TypeTo>
TypeTo convert(TypeFrom &from)
{
    return static_cast<TypeTo>(from);
}

template <>
std::string convert<std::wstring, std::string>(std::wstring &from)
{
    return std::string(from.begin(), from.end());
}

The first template I can use without using the types

int c = myMin(1,2);

But for the second template I have to use the types

std::string  st = convert<std::wstring, std::string>(sw);

I can not use it without:

std::string  st = convert(sw);  // this fails with the error "no accordance found for convet<TypeFrom, TypeTo>(wstring)"

Any idea why is that?

Upvotes: 1

Views: 89

Answers (1)

Holt
Holt

Reputation: 37606

Template argument cannot be deduced from return type of a function. You could swap the order of your template parameter to be able to do type deduction of the input argument(s):

template <class TypeTo, class TypeFrom >
TypeTo convert(TypeFrom &from)
{
    return static_cast<TypeTo>(from);
}

template <>
std::string convert<std::string, std::wstring>(std::wstring &from)
{
    return std::string(from.begin(), from.end());
}

// Partial deduction
std::string st = convert<std::string>(sw);

Basically, you cannot do convert(sw) because it may be ambiguous in many cases, e.g.:

// Call without using the return value
convert(sw);

// Call with return value sent to an overloaded function
void g (std::string) ;
void g (int) ;
g(convert(sw));

AFAIK, the same restriction applies to overloaded function (for the same reason). You cannot have in C++ (and in many languages such as Java), the following:

int f ();
float f ();

Actually, if you think about it, even your call is ambiguous because std::string has multiple constructors, so should I do:

std::string st = convert <std::string> (sw) ; // Copy constructor
std::string st = convert <const char *> (sw) ; // Constructor from const char *

The main idea is that while it may not be ambiguous for you (while would I convert to const char * instead of directly std::string?), it is ambiguous for the compiler, and it is not the compiler role to make that kind of choices.

Upvotes: 2

Related Questions