考虑以下代码:
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?)和答案:
In plain word, odr-used means something(variable or function) is used in a context where the definition of it must be present.
在第一种情况下(变量 t
),变量 VALUE
没有被使用,因为只需要它的值。但在第二种情况下,为什么代码无法编译?如果我传递 t
而不是传递 rvalue(?) 代码将编译正常。第二种情况与第一种情况有何不同以及为什么 VALUE
在这里使用 odr?
最佳答案
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&&
)
或者您可以使定义内联
(使用constexpr
最简单):
class Test {
public:
static constexpr int VALUE = 100;
};
关于c++ - 为什么这里要用const静态变量odr-?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61665005/