John Dibling
John Dibling

Reputation: 101456

Defining a Template Member of a Template Class separately from the Declaration

#include <cstdlib>

template<class A> struct Foo
{
    template<class B> static bool Bar();
};

template<class B> template<class A>  bool Foo<A>::Bar<B>()
{
    return true;
}

int main()
{
    bool b = Foo<int>::Bar<long>();
    b;
}

This results in a linker error:

main.obj : error LNK2019: unresolved external symbol "public: static bool __cdecl Foo<int>::Bar<long>(void)" (??$Bar@J@?$Foo@H@@SA_NXZ) referenced in function main

I need to define this member function outside of the class template's declaration. In other words, I cannot do this:

#include <cstdlib>
template<class A> struct Foo
{
    template<class B> static bool Bar()
    {
        return true;
    }
};

int main()
{
    bool b = Foo<int>::Bar<long>();
    b;
}

What am I missing? How can I define this member function template? What's the needed syntax?

Note: I am using MSVC 2008, in case that's relevant.

EDIT

The first thing I tried was to reverse the order of template<class A> and template<class B>:

#include <cstdlib>

template<class A> struct Foo
{
    template<class B> static bool Bar();
};

template<class A> template<class B>  bool Foo<A>::Bar<B>()
{
    return true;
}

int main()
{
    bool b = Foo<int>::Bar<long>();
    b;
}

This resulted in a compiler error:

.\main.cpp(11) : error C2768: 'Foo<A>::Bar' : illegal use of explicit template arguments

On the closing brace of the definition for the Bar function.

Upvotes: 4

Views: 230

Answers (2)

Potatoswatter
Potatoswatter

Reputation: 137780

Just reverse the order of template<class B> template<class A>. The second one is "inner" and goes with the member declaration. See §14.5.2/1.

Also, as John points out, remove the parameter-list from Bar<B>.

// "outer" template: this parameter gets substituted to create "inner" template
template< class A >

// "inner" template stands alone after "outer" substitution
template< class B >

bool
// This will just be a class name after "outer" substitution.
      foo<A>
// This has usual function template syntax
             :: Bar() {

Upvotes: 3

John Calsbeek
John Calsbeek

Reputation: 36497

This works for me:

template<class A>
template<class B>
bool Foo<A>::Bar()
{
    return true;
}

The order in which you write the two template specifiers matters (the outer template comes first). Also, if you actually put <B> on the name of the function template, at least one compiler (GCC) thinks you're trying to partially specialize the function Bar, which is impossible.

Upvotes: 2

Related Questions