简体   繁体   English

类模板的静态成员错误

[英]static member of class template error

I have a problem with this code snippet: 我对此代码段有疑问:

template <typename T>
struct S
{
  static int a;
};

template <typename T>
decltype(S<T>::a) S<T>::a;

clang-3.4 says: clang-3.4说:

s.cpp:8:25: error: redefinition of 'a' with a different type: 'decltype(S<T>::a)' vs 'int'
decltype(S<T>::a) S<T>::a;
                        ^
s.cpp:4:14: note: previous definition is here
  static int a;
             ^
1 error generated.

But gcc-4.8.2 accepts. 但是gcc-4.8.2接受了。 Which of the compilers is right? 哪个编译器是对的? Should I avoid such code in the future? 我将来应该避免这样的代码吗?

Clang is demanding that the definition match the declaration at template definition time, whereas GCC and others defer matching until instantiation time (which never even happens for your example). Clang要求定义在模板定义时匹配声明,而GCC和其他人推迟匹配直到实例化时间(从来没有发生过你的例子)。

Clang accepts this: Clang接受这个:

#include <type_traits>

template <typename T>
struct S
{
  static int a;
};

template <typename T>
typename std::enable_if< true, int >::type S<T>::a; // Resolves before instantiation

but rejects this small change: 但拒绝这个小小的变化:

template <typename T>
typename std::enable_if< std::is_same< T, T >::value, int >::type S<T>::a;

I cannot recall where the standard dictates when object declaration matching occurs, but I suspect that Clang is within its rights to reject the code. 我不记得在发生对象声明匹配时标准规定的位置,但我怀疑Clang是否有权拒绝代码。 The intent of the standard, if I recall correctly, is that each declaration matches exactly one definition, and that mapping may be determined before instantiation time. 如果我没记错的话,标准的意图是每个声明只匹配一个定义,并且可以在实例化时间之前确定该映射。

With the looser rule that GCC is apparently applying, you could have two member declarations and two definitions, but each definition may finalize either of the declarations depending on the template parameters. 使用GCC显然适用的更宽松的规则,您可以有两个成员声明和两个定义,但每个定义可以根据模板参数完成任一个声明。

The code which GCC and MSVC are accepting is ill-formed, no diagnosis required… pending finding the actual standardese buried somewhere in §3 [basic], §7 [dcl.dcl], §8 [dcl.decl], §14 [temp], or maybe somewhere else. GCC和MSVC正在接受的代码是不正确的,不需要诊断......等待在[§3[基本],§7[dcl.dcl],§8[dcl.decl],§14中找到埋藏的实际标准。温度],或者其他地方。


I still cannot find what rule matches object definitions to preceding declarations, but §14.4/2 dictates that decltype(…) cannot be the equivalent (I assume in the declarative sense) to int . 我仍然无法找到哪些规则将对象定义与前面的声明匹配,但§14.4/ 2规定decltype(…)不能与int等效(我假设在声明意义上)。

If an expression e involves a template parameter, decltype(e) denotes a unique dependent type. 如果表达式e涉及模板参数,则decltype(e)表示唯一的依赖类型。 Two such decltype-specifiers refer to the same type only if their expressions are equivalent (14.5.6.1). 两个这样的decltype-specifiers只有在它们的表达式是等价的时才引用相同的类型(14.5.6.1)。 [ Note: however, it may be aliased, eg, by a typedef-name. [ 注意:但是,它可能是别名,例如,通过typedef-name。 end note ] - 结束说明 ]

I'm pretty sure that equivalence, not mere aliasing, is necessary for the definition to match the declaration. 我很确定定义匹配声明需要等效,而不仅仅是别名。 §14.5.6.1 delves pretty deep into this territory, except it is specifically discussing function signatures. §14.5.6.1深入研究这个领域,除非它专门讨论功能签名。

I think Clang might be right in rejecting this. 我认为Clang 可能会拒绝这一点。 14.2p2 says about decltype(e) 关于decltype(e) 14.2p2说

If an expression e involves a template parameter, decltype(e) denotes a unique dependent type. 如果表达式e涉及模板参数,则decltype(e)表示唯一的依赖类型。

In DR #2 , the discussion trace says DR#2中 ,讨论描述说

My opinion (which I think matches several posted on the reflector recently) is that the out-of-class definition must match the declaration in the template. 我的观点(我认为与最近在反射器上发布的几个相匹配)是,类外定义必须与模板中的声明匹配。

... ...

In general, if you can match the declarations up using only information from the template, then the declaration is valid. 通常,如果只使用模板中的信息匹配声明,则声明有效。

I think it still matches if one of them uses a typedef (as demonstrated in the DR), because S<T>::type is a member of the current instantiation and the type aliased can be looked up directly. 我认为如果其中一个使用typedef(如DR中所示),它仍然匹配,因为S<T>::type是当前实例化的成员,并且可以直接查找别名类型。 But a decltype(e) , as specified above, will always denote a unique type (during template parse time) except with respect to another decltype(e) that specifies an equivalent expression. 但是,如上所述, decltype(e)将始终表示唯一类型(在模板分析时间期间),除了指定等效表达式的另一个decltype(e)


Why did I say might ? 为什么我说的威力 Because of 14.6p8 因为14.6p8

No diagnostic shall be issued for a template for which a valid specialization can be generated. 不能为可以生成有效特化的模板发出诊断。

One could read this as saying the type equivalence check is simply delayed till after instantiation. 人们可以读到这一点,因为类型等价检查只是延迟到实例化之后。 This, however, would contradict the discussion trace in the DR I think, because they say "if you can match the declarations up using only information from the template, then the declaration is valid" (and I assume the author of this statement meant to be exhaustive about the situations when the declaration is valid). 然而,这与我认为的DR中的讨论痕迹相矛盾,因为他们说“如果你只能使用模板中的信息来匹配声明,那么声明是有效的”(我认为这个声明的作者意味着在声明有效的情况下详尽无遗)。

For me clang is broken here. 对我来说,clang在这里打破了。

All combinations with decltype will fail. 所有与decltype的组合都将失败。 Without decltype it works. 没有decltype它工作。

template <typename T>
struct S
{   
      static int a;

      using type = decltype( a );
      typedef decltype( a ) type2;
};  

template <typename T>
1) decltype(S<T>::a) S<T>::a;
2) int S<T>::a;
3) typename S<T>::type S<T>::a;
4) typename S<T>::type2 S<T>::a;

1 gcc works, clang fails 1 gcc的作品,clang失败了

2 gcc + clang works 2 gcc + clang的作品

3 gcc works, clang fails 3 gcc作品,clang失败

4 gcc works, clang fails 4 gcc的作品,clang失败了

I did some more tries to work around the problem, but could not have any success. 我做了一些尝试解决问题,但没有取得任何成功。

There are some more discussions on that kind of problems: C++ Static member initalization (template fun inside) 关于这类问题还有一些讨论: C ++静态成员初始化(模板内部有趣)

Edit: I found that this topic is simply "not resolved" in the standard until now and clang did not implemented it: Take a look at: http://clang.llvm.org/cxx_dr_status.html ( point 205 ) 编辑:我发现这个主题在标准中只是“未解决”,直到现在并且clang没有实现它:看看: http//clang.llvm.org/cxx_dr_status.html (点205)

I hope that I did not misunderstood the page. 我希望我没有误解这个页面。 Feel free to correct my interpretation. 随意纠正我的解释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM