Reputation: 2321
I am trying to call a template class member function specialization that returns a value from within the class's constructor, and I cannot seem to find the correct syntax (if it exists). Below is my code, and, below that, the error messages from the compiler (not the linker).
#include <iostream>
class A {};
class B {};
template <typename T>
class C
{
public:
C()
{
std::cout << "C constructed." << std::endl;
std::cout << name() << std::endl;;
}
template constexpr const char * name();
};
template <> const char * C<A>::name() { return "You got an A."; }
template <> const char * C<B>::name() { return "You got a B."; }
int main()
{
C<A> c_a;
C<B> c_b;
return 0;
}
Error messages: g++ -std=c++11 -o t1 t1.cpp t1.cpp:19:18: error: expected ‘<’ before ‘constexpr’ template constexpr const char * name(); ^ t1.cpp:22:26: error: template-id ‘name<>’ for ‘const char* C::name()’ does not match any template declaration template <> const char * C::name() { return "You got an A."; } ^ t1.cpp:22:37: note: saw 1 ‘template<>’, need 2 for specializing a member function template template <> const char * C::name() { return "You got an A."; } ^ t1.cpp:23:26: error: template-id ‘name<>’ for ‘const char* C::name()’ does not match any template declaration template <> const char * C::name() { return "You got a B."; } ^ t1.cpp:23:37: note: saw 1 ‘template<>’, need 2 for specializing a member function template template <> const char * C::name() { return "You got a B."; }
I have searched and found many discussions about code that elicits this error message, but neither the cases nor the advice seem to be close enough to be relevant. Also, if I do not try to return anything from the specialized member function--if it has return type void and simply prints to cout--then it works as I would expect, i.e., I see the printed text with the right values.
Is it possible to do what I am trying to do? If so, how? Thanks!
Upvotes: 0
Views: 435
Reputation: 2321
For the record, I found a solution to the exact problem I had posted--i.e., using a member function instead of a static (or global) function, here.
#include <iostream>
class A {};
class B {};
template <typename T>
class C
{
template <typename U> struct type {};
public:
C()
{
std::cout << "C constructed." << std::endl;
std::cout << name<T>() << std::endl;;
}
template <typename U> constexpr const char * name()
{
return name(type<U>());
}
private:
template <typename U> constexpr const char * name(type<U>) {}
constexpr const char * name(type<A>) { return "You got an A."; }
constexpr const char * name(type<B>) { return "You got an B."; }
};
int main()
{
C<A> c_a;
C<B> c_b;
return 0;
}
Upvotes: 0
Reputation: 6131
You are complicating it a bit. There is no need for "template" in the function declaration. It's just an ordinary function that happens to be inside a class template, and you want to specialize it for certain T's. Here's a way to do that:
#include <iostream>
class A {};
class B {};
template <typename T>
class C {
public:
C() {
std::cout << "C constructed." << std::endl;
std::cout << name() << std::endl;;
}
static constexpr const char * name();
};
template <> constexpr const char * C<A>::name() { return "You got an A."; }
template <> constexpr const char * C<B>::name() { return "You got a B."; }
int main() {
C<A> c_a;
C<B> c_b;
}
Upvotes: 2
Reputation: 218148
Syntax would be:
template <typename T>
class C
{
public:
C()
{
std::cout << "C constructed." << std::endl;
std::cout << name() << std::endl;;
}
constexpr const char* name();
};
template <> constexpr const char * C<A>::name() { return "You got an A."; }
template <> constexpr const char * C<B>::name() { return "You got a B."; }
Upvotes: 6