为什么我们不能在模板静态成员初始化中使用auto?

时间:2015-01-18 18:15:24

标签: c++ templates c++11 static

以下代码

template <typename MemberType>
struct Holder {
    static MemberType member;
};

template <typename MemberType>
auto Holder<MemberType>::member;
如果我们尝试访问Holder :: member:

在MSVS 2013中产生错误C2371

  

错误C2371:&#39;会员&#39; :重新定义;不同的基本类型

但是,如果在初始化时我们使用模板参数名称而不是&#39; auto&#39;关键字

template <typename MemberType>
MemberType Holder<MemberType>::member;

按预期编译。那么,在这种情况下编译器无法推断静态成员类型的原因是什么?

1 个答案:

答案 0 :(得分:1)

使用占位符auto / decltype(auto)的变量声明必须具有要推断的变量类型的初始值设定项:

  

使用autodecltype(auto)声明的变量类型是从其初始化程序推导出来的。在块(6.3),命名空间范围(3.3.6)和 for-init-statement (6.5.3)中声明变量时,允许使用此方法。   autodecltype(auto)将在 decl-specifier-seq decl-specifier中显示为 decl-specifiers 之一seq 后面应跟着一个或多个 init-declarators ,每个 init-declarators 都应有一个非空初始值设定项

您的示例没有定义初始值设定项,因此您的代码格式不正确。

静态成员的定义可能有占位符,但示例中的问题与您使用模板的事实有关,静态成员的声明依赖于模板参数。例如,这个定义不会编译:

template <typename MemberType>
auto Holder<MemberType>::member = 42; // error: redefinition of 'member' with
                                    // a different type: 'int' vs 'MemberType'

Holder<MemberType>会导致隐式实例化,编译器将查看Holder<MemberType>::member的声明。编译器在此实例化时不知道从初始化器(int)推导出的类型是否与MemberType匹配,这就是为什么你得到奇怪的错误&#34; {{1 }} vs int&#34;。

如果您创建数据成员的显式特化,则上述代码有效,因为在实例化时已知MemberType

MemberType