考虑以下代码:

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/

10-09 15:33