9

我正在尝试执行以下操作:

template <typename T>
struct A
{
    template <typename U>
    struct AA
    {
    };
};

template <typename V, template <typename> class W = A<V>::AA> // Causes C3202
struct B
{
};

但是 Visual Studio 2010 编译器会吐出:

错误 C3202:“AA”:模板参数“”的默认参数无效,应为类模板

如果我将 B 替换为以下模板:

// Replace "T" with "int"
template <typename V, template <typename> class W = A<int>::AA>
struct B
{
};

代码编译得很好,但不是我想要的。如果原件不是合法的 C++,是否有替代方案为“B”模板的用户提供类似的界面?

4

2 回答 2

3

您的代码不是有效的 C++ 代码。请参阅下面的引文。


C++03

14.2 模板特化的名称 [temp.names]

14.2/4

当成员模板特化的名称出现在postfix -expression.之后或之后,或者在限定 ID中的nested-name-specifier之后,并且 postfix-expression 或qualified-id 显式依赖于模板参数(14.6.2 ),成员模板名称必须以关键字 为前缀。否则,该名称被假定为命名非模板。->template

14.2/5

如果以关键字template为前缀的名称不是成员模板的名称,则程序格式错误。[注意:关键字可能不适用于类模板的非模板成员。] 此外,如果后缀表达式限定ID未出现在模板范围内,则template成员模板的名称不应以关键字为前缀. [注:与前缀的情况一样,在非严格必要的情况下允许使用前缀;即,当or左侧的表达式或嵌套名称说明符不依赖于模板参数时。]templatetypenametemplate->.


C++11

14.2 模板特化的名称 [temp.names]

14.2/4

当成员模板特化的名称出现在postfix -expression.之后或之后,或者在 qualified-id 中的nested - name-specifier之后,并且postfix-expression的对象表达式是类型相关的或nested-name-specifierqualified-id中指的是依赖类型,但名称不是当前实例化的成员(14.6.2.1),成员模板名称必须以关键字为前缀。否则,该名称被假定为命名非模板。->template

14.2/5

以关键字为前缀的名称template应为模板 ID或名称应指类模板。[注意:关键字template可能不适用于类模板的非模板成员。— end note ] [注意:typename前缀的情况一样,template前缀在不是绝对必要的情况下是允许的;即,当嵌套名称说明符->或or左侧的表达式.不依赖于模板参数时,或者使用未出现在模板的范围内。— 尾注] [示例:

// ...

template <class T> struct B {
  template <class T2> struct C { };
};

// OK: T::template C names a class template:
template <class T, template <class X> class TT = T::template C> struct D { };

D<B<int> > db;

—结束示例]


符合标准的代码

所以在这种情况下正确的语法是:

template <typename T>
struct A
{
    template <typename U>
    struct AA
    {
    };
};

template <typename V, template <typename> class W = A<V>::template AA>
//                                                      ^^^^^^^^^^^
struct B
{
};

不幸的是, VC2010也不理解有效的语法。

于 2014-09-12T18:30:10.063 回答
1

根据您对“相似”的定义,您可以将B模板定义更改为

template <typename V, typename W = A<V>>
struct B
{
};

在 struct 内部B,您可以访问内部模板

W::template AA< some_type >

但是,您的用户需要提供包装在类中的类似 AA 的模板,就像您的struct A.

您还可以降低对编译器兼容性的要求并要求 MSVC 2013+。

于 2014-09-12T16:19:43.243 回答