0
votes

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!

3
The name() function isn't itself a template, so why the template?Bo Persson
You are right. What I actually intended was a member function of a specialization of the class, but I was using syntax as if it were a specialization of a template function of that template class. This was my mistake. (See my solution.) Thanks.Amittai Aviram
Oops! While I was writing the above reply, somebody posted a solution equivalent to the one I had found. Thanks!Amittai Aviram

3 Answers

6
votes

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."; }

Demo

2
votes

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;
}
0
votes

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;
}