我有一个配置类
// config.hpp
class Config {
public:
static constexpr int a = 1;
static constexpr int b = 1;
}
并包含在main.cpp 中
// main.cpp
#include "config.hpp"
int main () {
std::cout << Config::a << std::endl; // this is ok
std::shared_ptr<otherClass> stream = std::make_shared<otherClass>(
Config::a); // compile error
}
编译器说undefined reference to Config::a
它在使用cout
时起作用,但在shared_ptr
构造函数内不起作用。
我不知道为什么会发生这种事。
请注意,std::make_shared通过引用获取参数,这会导致Config::a
被odr使用,因为它将被绑定到引用参数,那么它在命名空间范围内的定义是必需的(在C++17之前)。
另一方面,std::cout << Config::a
不会导致使用Config::a
,因为std::basic_stream::operator<lt;(int)按值取参数,然后Config::a
进行左值到右值的转换,请求复制初始化参数,因此不使用Config::a
。
如果一个对象是odr使用的,那么它的定义必须存在。您可以将定义(在实现文件中)添加为
constexpr int Config::a; // only necessary before C++17
请注意,它不能有初始值设定项。
实时
由于C++17constexpr
静态数据成员是隐式内联的,因此不再需要这样的定义,因此您的代码在C++17中运行良好。
如果
static
数据成员被声明为constexpr
,则它是隐式inline
,不需要在命名空间范围内重新声明。这种不带初始值设定项的重新声明(以前如上所示是必需的)仍然是允许的,但已被弃用。
实时
您的a是私有的,或者是public:需要对其进行预处理,或者使该类成为一个结构以获得默认的public。但这是在C++14下编译的https://godbolt.org/g/tS4M1Z
#include <iostream>
#include <memory>
struct Config {
static constexpr int a = 1;
static constexpr int b = 1;
};
struct otherClass {
otherClass( int c ) { }
};
int main () {
std::cout << Config::a << std::endl; // this is ok
std::shared_ptr<otherClass> stream = std::make_shared<otherClass>( Config::a ); // compile error
}