类模板的静态成员错误
static member of class template error
我对以下代码段有问题:
template <typename T>
struct S
{
static int a;
};
template <typename T>
decltype(S<T>::a) S<T>::a;
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.
但gcc-4.8.2
接受。哪个编译器是对的?我以后应该避免这样的代码吗?
Clang要求定义在模板定义时与声明匹配,而GCC和其他人则将匹配推迟到实例化时(这在您的示例中从未发生过)。
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
但拒绝这个小小的改变:
template <typename T>
typename std::enable_if< std::is_same< T, T >::value, int >::type S<T>::a;
我记不起标准在什么时候指定对象声明匹配,但我怀疑Clang有权拒绝代码。如果我没有记错的话,该标准的目的是每个声明都与一个定义完全匹配,并且可以在实例化之前确定映射。
GCC显然采用了更宽松的规则,您可以有两个成员声明和两个定义,但每个定义可能会根据模板参数最终确定其中一个声明。
GCC和MSVC接受的代码格式不正确,无需诊断……等待在§3[基本]、§7[dcl.dcl]、§8[dcl.dll]、§14[临时]或其他地方找到实际标准。
我仍然找不到什么规则将对象定义与前面的声明相匹配,但§14.4/2规定decltype(…)
不能等同于int
(我认为是在声明意义上)。
如果表达式e涉及模板参数
decltype(e)
表示唯一的依赖类型。两个这样的decltype说明符引用仅当它们的表达式相等时(14.5.6.1),才将其转换为相同类型。[注意:但是,它可能会被别名,例如通过typedef名称。--end注意]
我确信等价性,而不仅仅是别名,对于定义匹配声明是必要的。§14.5.6.1深入探讨了这一领域,只是专门讨论了函数签名。
我认为Clang拒绝这一点可能是正确的。14.2p2关于decltype(e)
如果表达式e包含一个模板参数,decltype(e)表示一个唯一的依赖类型。
在DR#2中,讨论跟踪显示
我的观点(我认为这与最近发布在反射器上的几个观点相匹配)是,类外定义必须与模板中的声明相匹配。
通常,如果仅使用模板中的信息即可匹配声明,则声明是有效的。
我认为如果其中一个使用typedef(如DR中所示),它仍然匹配,因为S<T>::type
是当前实例化的成员,并且可以直接查找别名类型。但是,如上所述,decltype(e)
将始终表示唯一类型(在模板解析时间期间),除了相对于指定等效表达式的另一个decltype(e)
。
为什么我说可能?由于14.6p8
对于可以生成有效专业化的模板,不得发布任何诊断。
可以将其理解为,类型等价性检查只是延迟到实例化之后。然而,我认为这将与DR中的讨论轨迹相矛盾,因为他们说"如果你可以只使用模板中的信息来匹配声明,那么声明是有效的"(我认为本声明的作者是为了详尽地说明声明有效的情况)。
对我来说,clang在这里被打破了。
所有具有decltype的组合都将失败。没有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工作,clang失败
2 gcc+clang作品
3 gcc工作,clang失败
4 gcc工作,clang失败
我做了更多的尝试来解决这个问题,但没有取得任何成功。
关于这类问题还有更多的讨论:C++静态成员初始化(内部模板乐趣)
编辑:直到现在,我发现这个主题在标准中根本"没有得到解决",clang也没有实现它:看看:http://clang.llvm.org/cxx_dr_status.html(点205)
我希望我没有误解这一页。请随意更正我的解释。
- 静态成员函数使用相同的名称时出现模板类型名称错误
- 为什么传递非静态成员函数会导致编译错误?
- 在 T 的静态成员中使用 sizeof(T) 的 c++ 错误
- 错误:无效使用非静态成员函数"int test::hotplug_callback(libusb_contex
- C :(不重复)积分静态成员初始化(不仅是声明!),导致链接器错误,原因
- 错误:在 C++ 中无效使用非静态成员函数
- C++类静态成员函数调用错误
- 结构内部的结构:"对非静态成员的非法引用"错误
- 在C 中,静态成员函数是否继承了?如果是,为什么没有出现歧义错误
- 在C 中获取Invalig使用非静态数据成员错误
- 非静态数据成员错误的使用无效
- gcc 和 clang 中 constexpr 静态成员变量的链接器错误
- C++ 线程函数指针实现返回错误无效使用非静态成员函数
- 错误:必须调用对非静态成员函数的引用 (2)
- C++ PTHREAD 错误:非静态成员函数的使用无效
- 私有静态成员 - 编译错误?
- 使用C ,使用SFINAE测试静态成员的存在,返回错误的值
- 我的错误,还是英特尔编译器的错误?非静态成员错误的大小
- c++中的静态成员错误
- 类模板的静态成员错误