考虑以下代码:
class Test {
public:
static const int VALUE = 100;
};
std::tuple<int> foo(std::tuple<int> value) {
return value;
}
int main()
{
auto t = std::make_tuple(Test::VALUE); // This compiles fine
auto t1 = foo(std::make_tuple(Test::VALUE)); // undefined reference to `Test::VALUE' linker error
}
根据另一个问题(What does it mean to "ODR-use" something?)和答案:
在第一种情况下(变量
t
),不使用VALUE
变量,因为只需要它的值即可。但是在第二种情况下,为什么代码无法编译?如果我将传递t
而不是传递的rvalue(?),则该代码可以正常编译。第二种情况与第一种情况有何不同?为什么在这里使用VALUE
? 最佳答案
make_tuple
通过const int&
接受参数(因为它是一个常量左值,并且接受T&&
参数),并且将引用绑定(bind)到值是ODR用途。
两种情况均为病态,无需诊断。例如,在gcc的优化级别较高的情况下,整个程序都会被优化,并且没有链接器错误,在没有优化的情况下,两个语句都给出链接器错误。
要使其不用于ODR,可以将其转换为右值:
// Various ways to force the lvalue-to-rvalue conversion
auto t = std::make_tuple(int(Test::VALUE));
auto t1 = foo(std::make_tuple((void(), Test::VALUE)));
auto t2 = foo(std::make_tuple(+Test::VALUE));
(因此
std::make_tuple
接受一个临时的int&&
)或者,您可以定义
inline
(最简单的使用constexpr
):class Test {
public:
static constexpr int VALUE = 100;
};
关于c++ - 为什么在这里使用const静态变量odr?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61665005/