#include <complex>
struct S
{
static std::complex<double> constexpr c;
};
Run Code Online (Sandbox Code Playgroud)
gcc生成错误,因为缺少初始化程序.Clang和MSVC不会生成错误.
据我所知,constexpr静态数据成员必须有一个初始化程序,即使它是具有可以不带参数调用的构造函数的类类型(如本例所示).不幸的是,我没有最新的C++标准来支持我的假设.
所以正确的代码应该用构造函数初始化,例如:
struct S
{
static std::complex<double> constexpr c {};
};
Run Code Online (Sandbox Code Playgroud)
任何人都可以证明哪个编译器是正确的,哪个是错的?
Windows上的Clang/LLVM 7.0.1 每个TU初始化一次内联静态数据成员.据我所知,C++ 17这是不正确的.
尽管可以在多个TU中定义内联变量,但编译器和/或链接器必须确保它在程序中仅存在一次,因此仅初始化一次.就像多重定义的内联函数一样,在程序中只存在一次.请参阅以下小程序:
// header.h
#include <iostream>
struct A
{
A() { std::cout << "ctor " << this << std::endl; }
~A() { std::cout << "dtor " << this << std::endl; }
void f() { std::cout << "f " << this << std::endl; }
};
struct S
{
inline static A a; // C++17 inline variable, thus also a definition
};
Run Code Online (Sandbox Code Playgroud)
// TU1.cpp
#include "header.h"
int main()
{
S::a.f();
}
Run Code Online (Sandbox Code Playgroud)
// TU2.cpp
#include "header.h"
Run Code Online (Sandbox Code Playgroud)
// …
#include <type_traits>
template<bool b>
struct S
{
template<typename = std::enable_if_t<b>>
S() {}
template<typename = std::enable_if_t<!b>>
S(int) {}
};
S<true> s{}; // error in clang/gcc, OK in VC2017
S<false> s{0}; // error in clang/gcc, OK in VC2017
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,clang/gcc尝试实例化由于SFINAE而实际应该丢弃的ctor.错误消息是:
错误:'std :: enable_if <false,void>'中没有名为'type'的类型; 'enable_if'不能用于禁用此声明
clang/gcc对另一个ctor的实例化是不正确的,因为它不应该在可能的重载列表中,对吧?
但在我提交错误之前,我想阅读别人的想法.也许我说得不对劲......
//呃
template<int> extern int const i;
Run Code Online (Sandbox Code Playgroud)
// i.cpp
#include "i.h"
template<> extern int constexpr i<0> = 42;
Run Code Online (Sandbox Code Playgroud)
// main.cpp
#include "i.h"
int main()
{
return i<0>;
}
Run Code Online (Sandbox Code Playgroud)
在C++ 14/17模式下,这将返回带有clang的42,但是与gcc一起出错:"显式模板专门化不能有存储类".
这是gcc中的错误吗?