我有一个Config类
// 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
构造函数内无效。
我不知道为什么会这样。
答案 0 :(得分:7)
请注意,std::make_shared通过引用获取参数,这会导致Config::a
为odr-used,因为它将绑定到引用参数,然后在命名空间范围内定义它是必需的(在C ++ 17之前)。
另一方面,std::cout << Config::a
不会导致Config::a
被使用,因为std::basic_ostream::operator<< (int)按值获取参数,Config::a
则受制于Config::a
要求复制初始化参数的左值到右值转换,因此constexpr int Config::a; // only necessary before C++17
不会被使用。
如果对象使用了odr,则其定义必须存在。您可以将定义(在实现文件中)添加为
static
请注意,它不能有初始化程序。
由于C ++ 17 constexpr
static data member是隐式内联的,因此不再需要这样的定义,因此您的代码在C ++ 17中运行良好。
如果
constexpr
数据成员被声明为inline
,则它是隐式{{1}},并且不需要在命名空间范围内重新声明。这种重新声明没有初始化程序(以前需要如上所示)仍然是允许的,但已被弃用。
答案 1 :(得分:1)
你的a是私有的,或者是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
}