jma
jma

Reputation: 3779

C++ template specialisation, but no match found

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

Answers (2)

Some programmer dude
Some programmer dude

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

YSC
YSC

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

Related Questions