例如:
class example{
public:
template <class T> static constexpr T var = T(1.5);
};
int main(){
int a = example::var<int>;
example obj;
int b = obj.var<int>;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC会产生以下错误:
'example::var<T>' is not a function template和'var' is not a member template function
Clang正确编译第一个但是第二个产生错误: cannot refer to member 'var' in 'example' with '.'
根据C++ 14标准(ISO/IEC 14882:2014):
第14节,第1段.
类作用域中的变量模板是静态数据成员模板.
第9.4节,第2段.
可以使用qualified-id表达式X :: s来引用类X的静态成员; 没有必要使用类成员访问语法(5.2.5)来引用静态成员.可以使用类成员访问语法来引用静态成员,在这种情况下,评估对象表达式.
因此,可以以两种方式引用恕我直言,类范围的变量模板(即,静态数据成员模板).它可能是编译器中的错误吗?
我发现试图证明这种行为的唯一理由是第9.4.2节第1段中的这句话:
静态数据成员不是类的子对象的一部分.
但是,上述两个段落仍然有效.此外,我尝试了同样的例子,引用其他静态成员,如变量,函数和函数模板,并且所有这些成员都在GCC和Clang中成功编译.
class example{
public:
static int constexpr variable = 1;
void static function(){ …Run Code Online (Sandbox Code Playgroud) #include <stdlib.h>
void *operator new[](size_t size, int n){
if( size != 0 && n != 0 )
return calloc(n, size);
return calloc(1, 1);
}
int main(){
int * p1;
const int i = 0;
// p1 = new (20) int[i] ; // Case 1 (OK)
p1 = new (20) (int[i]); // Case 2 (Warning)
if( p1 == 0 )
return 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码(https://godbolt.org/g/hjo7Xn)与Clang 6.0.0成功编译,但是,GCC 7.3发出警告说在C++中禁止使用零长度数组.如果删除了括号(案例1),警告就会消失.
与静态分配的零长度数组(C++ 03:8.3.4/1)不同,允许动态分配的零长度数组(C++ 03:5.3.4/6).尽管如此,在C++标准中,只有在遵循new-expression的两个可能语法路径之一时,才明确允许后者,即具有new-type-id且没有括号的路径(Case 1).
是否允许C++标准在第二个语法路径后使用带有零长度数组的new-expression,即使用 …
void f( int , const int (&)[2] = {}) { } // #1
void f( int , const int (&)[1] ) { } // #2
// void f(const int&, const int (&)[1] ) { } // #2_original
void test() {
const int x = 17;
auto g = [](auto a) {
f(x); // OK: calls #1, does not capture x
};
auto g2 = [ /* = */ ](auto a) {
int selector[ sizeof(a) == 1 ? 1 : 2 …Run Code Online (Sandbox Code Playgroud)