0

I have a template function:

template<typename T>
void foo(T const & t);

And some specialisations of that function:

template<> void foo<int>(int const & t) {
  cout << t << endl;
}

template<> void foo<const char *>(const char * const & t) {
  cout << t << endl;
}

And some ways I want to call that function:

foo(3);
foo("Hello, world.");

But I can't figure out how to formulate the template so that template type deduction gets literals of both int and const char * right. If I do the above, then I get undefined reference to void foo<char [14]>(char const [14] &). I tried recasting the template like this:

template<typename T>
void foo(T t);

template<> void foo<int>(int t) { ... }
template<> void foo<const char *>(const char * t) { ... }

which works, but of course now I get call-by-value semantics, requiring any class types that I use as the template parameter to have a copy constructor.

Is there no way to write a pass-by-reference template function with a const char * specialisation that works?

Tom
  • 7,269
  • 1
  • 42
  • 69
  • 2
    [FYI] String literals have the type `const char[n]` not `const char *`. – NathanOliver Aug 03 '16 at 15:26
  • Any reason to prefer `template<> void foo(int const & t)` over `template<> void foo(int t)`? I prefer to pass by value primitive type instead – Danh Aug 03 '16 at 15:33

1 Answers1

4

This:

foo("Hello, world.");

Doesn't call foo<const char*>. It calls foo<char[14]>, since foo takes a T const&. Your specialization isn't called since it isn't the same type as the template.

That said, just don't specialize. Overload:

template<typename T>
void foo(T const& );

void foo(int const& );

void foo(char const* );

It's way easier to reason about and is more likely to do what you actually want.

Barry
  • 286,269
  • 29
  • 621
  • 977