Reputation: 3779
I have a deserialisation function. With templates, I'd like to be able to get the thing that I'm deserialising. In other words, I'd like a function that computes the serialised thing and another that handles deserialisation. If I name them differently, I have no problem, and, indeed, this is so easy a solution that I will surely just do that. But it bothers me that I don't understand why the following isn't acceptable.
#include <string>
using std::string;
// In real life, fetch the stringified object.
template<>
string foo(int x);
// In real life, fetch an object and deserialize it.
template <typename T>
T foo(int x) {
string s = foo<string>(x);
T t;
// Do something with s.
return t;
}
template<>
string foo(int x) { return std::to_string(x); }
Compiling with
clang -Wall -Wextra -std=c++14 foo.cc -o foo
says
foo.cc:6:8: error: no function template matches function template specialization 'foo'
string foo(int x);
So the obvious solution is just to change the first function to string make_foo(int x)
and be done with it.
To help me learn, I've been trying to understand why what I wrote above fails. Note that I also tried template <> string foo<string>(int x)
, though I would think that the specialisation could be inferred.
Upvotes: 0
Views: 2002
Reputation: 409166
The compiler needs to see the generic declaration before you can declare a specialization, so simply change the order of the declarations.
Upvotes: 2
Reputation: 40060
The specialization can't be inferred here because the return type of a function is not part of the function declaration. Thus, if no function parameter type depends on the template parameter, you have to write the full specialization:
template<>
std::string foo<std::string>(int x)
{
/* ... */
}
For instance, in the following case, you can let the compiler infer the specialization:
template<class T>
void f(T arg)
{
// generic case
/* ... */
}
template<>
void f(bool arg)
{
// bool case
/* ... */
}
Upvotes: 1