shrike shrike - 1 month ago 11
C++ Question

How to set, as default template parameter, a nested template class instanciation depending on other parameters

I have the following template class & sample classes :

template<typename A, typename B, typename C = typename A::Nested<B>>
struct X
{
X()
{
std::cout << "A is : " << A::who() << std::endl;
std::cout << "B is : " << B::who() << std::endl;
std::cout << "C is : " << C::who() << std::endl;
}
};

struct Bsample
{
static const char* who() { return "Bsample"; }
};

struct Asample
{
template<typename B>
struct Nested;
template<>
struct Nested<Bsample>
{
static const char* who() { return "Asample::Nested<Bsample>"; }
};
static const char* who() { return "Asample"; }
};


When using vc14, the above code compiles just fine and produces the expected behavior for an instanciation of
X<Asample, Bsample>
defaulting template parameter
C
to
Asample::Nested<Bsample>
.

However, when compiling with GCC 5.1, I get the following error :

prog.cpp:4:65: error: expected '>' before '<' token
template<typename A, typename B, typename C = typename A::Nested<B>>
^


I tried several combinations to declare the default value for template parameter
C
, using
template
,
typename
, ... but did not succeed in compiling this code with GCC.

How to make this code compliant to C++ standard and compile with GCC ?

Thanks for help

Answer

You need both typename and template here:

template<typename A, typename B, typename C = typename A::template Nested<B>>

The template says than A::Nested is a template, and the typename says that A::Nested<B> names a type.

You also need to move the specialization of Asample::Nested out of the Asample definition:

struct Asample
{
    template<typename B>
    struct Nested;

    static const char* who()    { return "Asample"; }
};

template<>
struct Asample::Nested<Bsample>
{
    static const char* who()    { return "Asample::Nested<Bsample>"; }
}; 

Live demo