如何根据其他参数设置嵌套模板类instanciation作为默认模板参数

时间:2016-11-09 09:04:47

标签: c++ templates

我有以下模板类&样本类:

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

使用vc14时,上面的代码编译得很好,并为X<Asample, Bsample>默认模板参数CAsample::Nested<Bsample>的实例化产生了预期的行为。

但是,在使用GCC 5.1进行编译时,我收到以下错误:

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

我尝试了几种组合来使用Ctemplate来声明模板参数typename的默认值,但是没有成功使用GCC编译此代码。

如何使此代码符合C ++标准并使用GCC进行编译?

感谢您的帮助

编辑:除了TartanLlama接受的答案

除了TartanLlama接受的答案之外,我还必须在结束模板参数brakets之间插入一个空格(空格):

template<typename A, typename B, typename C = typename A::Nested<B> >
//                                        blank (space) added here ^

否则,GCC发出以下错误(未指定选项-std=c++11时):

error: spurious '>>', use '>' to terminate a template argument list
 template<typename A, typename B, typename C = typename A::template Nested<B>>
                                                                            ^

2 个答案:

答案 0 :(得分:4)

您需要typename template

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

template表示A::Nested是一个模板,而typename表示A::Nested<B>表示一种类型。

您还需要将Asample::Nested的专业化移出Asample定义:

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

答案 1 :(得分:1)

您需要告诉编译器Nested是一个模板:

template<typename A, typename B, typename C = typename A::template Nested<B>>
struct X
{
    // ... 

无论如何,由于不同的错误,您的代码将无法编译:

error: explicit specialization in non-namespace scope 'struct Asample'
     template<>

您需要在命名空间范围内专门化Nested