Reputation: 3077
Consider the following simplified version of my code.
I have a template class A
, a template function Fill
, and a specialization of the function to work with basic types like int
or char
, and another specialization to work with A
:
#include <sstream>
#include <string>
#include <iostream>
template<size_t C>
class A
{
public:
A & operator=(std::string v) {
data[0] ='a';
return *this;
}
char data[C];
};
template<typename T> T Fill(std::string value, T default_value);
// Specialization for A<C>
template<size_t C>
A<C> Fill(std::string value, A<C> default_value)
{
if (value.empty())
return default_value;
A<C> result;
result = value;
return result;
}
// Specialization for int, double, char, etc
template<typename T>
T Fill(std::string value, T default_value)
{
if (value.empty())
return default_value;
T result;
std::istringstream(value) >> result;
return result;
}
void main()
{
int abc = Fill(/*Get a string somehow*/"123", 0); // OK
A<10> def;
def = std::string("111");
A<10> a;
a = Fill(/*Get a string somehow*/"abc", def); // OK
}
That works fine although I'm amazed that the compiler manages to match the parameter to the right template specialization.
The problem comes with some typedef
s that ease the use of A<x>
. Here is a simplified version:
typedef A<12> A12;
...
A<12> def12;
def12 = std::string("12");
A12 a12;
a12 = Fill(/*Get a string somehow*/"xyz", def12); // Not OK !
The compiler does not detect that the type A12
is actually A<12>
and uses the wrong specialization of the function, which does not compile because istringstream cannot parse with operator>>
into an A
.
How can I make it use the right template specialization ?
Upvotes: 2
Views: 164
Reputation: 35449
The compiler does not detect that the type A12 is actually A<12> and uses the wrong specialization of the function
Actually since you're passing A<12> def;
in your example (mistake?), the correct overload (see my comment on the question) should be picked. The fact that you're assigning the result to A12 a;
shouldn't affect overload resolution.
If you meant the opposite (passing A12
and assigning to whatever) then this could be a compiler deficiency. This works correctly here.
Upvotes: 0
Reputation: 168596
typedef A<12> A12;
...
A12 a12;
a12 = Fill(/*Get a string somehow*/"xyz", def); // Not OK !
In this example, you have not shown us the type of def
. Assuming that it is the same as the previous example, namely A<10>
, this will certainly fail.
In your template, the type of the second parameter must match the return type. Try this:
typedef A<12> A12;
...
A12 a12;
A12 def12;
a12 = Fill(/*Get a string somehow*/"xyz", def12); // OK !
Upvotes: 1
Reputation: 272467
Template specializations are not inferred via where you're assigning the return value to. You'll have to explicitly instantiate the correct version:
a12 = Fill<A<12> >("xyz", def);
(or whatever it is that you need...)
Upvotes: 4