C++ 类内类链接问题的静态constexpr
我试图创建类中定义的C++ 类内类链接问题的静态constexpr,c++,c++11,clang,C++,C++11,Clang,我试图创建类中定义的静态constexprs。我知道这个问题:,方法3现在可以了 但是,我的链接器有问题。它报告重复符号,可能是因为const到constepr重新定义。有没有办法做到这一点?我使用的是xcode 7 我正在尝试的代码是: class foo{ int _x; constexpr foo(int x) : _x(x) {} public: static const foo a, b, c; constexpr int x() const { ret
静态constexpr
s。我知道这个问题:,方法3现在可以了
但是,我的链接器有问题。它报告重复符号,可能是因为const
到constepr
重新定义。有没有办法做到这一点?我使用的是xcode 7
我正在尝试的代码是:
class foo{
int _x;
constexpr foo(int x) : _x(x) {}
public:
static const foo a, b, c;
constexpr int x() const { return _x; }
};
constexpr foo foo::a = foo(1), foo::b = foo(2), foo::c = foo(1);
将此文件包含在多个位置会导致链接器错误
3 duplicate symbols for architecture x86_64
我知道这就是问题所在,因为如果只包含一次,它就可以正常工作。移动
constexpr foo-foo::a=foo(1),foo::b=foo(2),foo::c=foo(1)
行到
.cc
文件。这一行定义了变量。一个变量可以声明任意多次,但只能在整个二进制文件中定义一次。与任何变量定义一样,您应该只将它放在一个转换单元中
将最后一行移出页眉。首先定义前三个静态常量变量,然后将它们定义为constexpr。因为constexpr静态成员必须是完整的,所以它不能在类本身的范围内。您的代码应该如下所示:
class foo {
int _x;
public:
constexpr foo(int x) : _x(x) {}
constexpr int x() const { return _x; }
};
constexpr foo a = foo{1}, b = foo{2}, c = foo{1};
如果您仍然希望foo成为静态成员,您可以使用以下小技巧:
class foo {
int _x;
constexpr foo(int x) : _x(x) {}
struct constants;
public:
constexpr int x() const { return _x; }
};
struct foo::constants {
constexpr static foo a = foo{1}, b = foo{2}, c = foo{1};
};
如果您使用的是C++14及之前的版本,请遵循此步骤。在C++17中,所有constexpr静态数据成员都是隐式内联的 现在为什么会出现链接错误? 有一个小规则称为一个定义规则,它规定在所有编译单元中可以有任意数量的声明,但只能有一个定义。根据问题中包含的代码片段,看起来您正在标题中定义静态成员。如果有两个编译单元包含头,那么就违反了规则。在我上面的代码示例中,您不应该再有这个错误,而应该有另一个错误:没有定义。constexpr值可能在编译时使用,但在运行时不可用。为此,必须在.cpp文件中声明:
#include "foo.h"
constexpr foo foo::constants::a;
constexpr foo foo::constants::b;
constexpr foo foo::constants::c;
现在,您的三个静态变量已正确声明和定义。除了Guillaume Racicot的答案之外,您还可以添加constexpr函数,该函数返回在其他位置定义的constexpr值的copy或const引用。或者每次调用构造函数并返回新实例,而不保留constexpr变量。 在VS2015上测试:
class foo {
int _x;
constexpr foo(int x) : _x(x) {}
struct constants;
public:
constexpr int x() const { return _x; }
static constexpr const foo &a();
static constexpr const foo &b();
static constexpr const foo &c();
static constexpr foo d() { return foo(5); }
};
struct foo::constants {
constexpr static foo a = foo{ 1 }, b = foo{ 2 }, c = foo{ 1 };
};
constexpr const foo &foo::a() { return constants::a; }
constexpr const foo &foo::b() { return constants::b; }
constexpr const foo &foo::c() { return constants::c; }
然后可以从foo的作用域中获取值,例如:
static\u断言(foo::a().x()==1,”代码>这样做会使它成为一个非constepr
,使静态断言(foo::a.x()==1,”)
失败。有没有办法将常量泄漏到foo
的范围内?我需要能够编写foo::a
。那么,constexpr
静态成员必须是完整的,因此不能直接在类本身中。第二个代码段做了一个小技巧,允许它仍然在foo
范围内。我还不知道其他的解决方法。