Hait
Hait

Reputation: 125

Calling template function from inner class

I have a class like this to call a function depending on the type. I try to compile it, but have error error C2059 syntax error : 'template'

class A
{
  call_1()
{
  B<type> b;
  b.template say(i);
}

template<class T>
    struct B
    {
        template <typename T, typename I>
        T say(I i) {
            return word;
        }
    };
    template<>
    struct B<void>
    {
        template <typename T, typename I>
        void say(I i) {
            /**/
        }
    };
}

What am I doing wrong?

Upvotes: 1

Views: 59

Answers (1)

Nikos C.
Nikos C.

Reputation: 51880

First, let's rewrite your example into something that is readable and is closer to being compilable, and we also print "1" or "2" in say() to know which function gets called:

#include <iostream>
using type = int;

class A {
    void call_1() {
        B<type> b;
        int i = 0;
        b.template say(i);
    }

    template<class T>
    struct B
    {
        template <typename T, typename I>
        T say(I i) {
            std::cout << "1\n";
            return T();
        }
    };

    template<>
    struct B<void>
    {
        template <typename T, typename I>
        void say(I i) {
            std::cout << "2\n";
        }
    };
};

OK, so first, you are trying to specialize B inside of A. This is not allowed, so let't move it outside of A:

using type = int;

class A {
    void call_1() {
        B<type> b;
        int i = 0;
        b.template say(i);
    }

    template<class T>
    struct B
    {
        template <typename T, typename I>
        T say(I i) {
            std::cout << "1\n";
            return T();
        }
    };
};

template<>
struct A::B<void>
{
    template <typename T, typename I>
    void say(I i) {
        std::cout << "2\n";
    }
};

Next up, you are using the same template parameter (T) in both B and say(). You don't need to repeat T, so let's delete it:

using type = int;

class A {
    void call_1() {
        B<type> b;
        int i = 0;
        b.template say(i);
    }

    template<class T>
    struct B
    {
        template <typename I>
        T say(I i) {
            std::cout << "1\n";
            return T();
        }
    };
};

template<>
struct A::B<void>
{
    template <typename I>
    void say(I i) {
        std::cout << "2\n";
    }
};

Finally, call_1() cannot be defined before the specialization of A::B, so we need to move it outside too:

using type = int;

class A {
    void call_1();

    template<class T>
    struct B
    {
        template <typename I>
        T say(I i) {
            std::cout << "1\n";
            return T();
        }
    };
};

template<>
struct A::B<void>
{
    template <typename I>
    void say(I i) {
        std::cout << "2\n";
    }
};

void A::call_1() {
    B<type> b;
    int i = 0;
    b.template say(i);
}

This should now compile and do what you want. Calling call_1() will print 1. If you change the type from int to void:

using type = void;

it will print 2.

Upvotes: 2

Related Questions