c++ - 为什么这里要用const静态变量odr-?

标签 c++ c++14

考虑以下代码:

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/

相关文章:

c++ - 正确的 set_socket_init_handler 语法或修改源代码以使用 websocket++ 打开 TCP_NODELAY

c++ - 对内部类型使用声明

c++ - 显式 void 指针作为函数参数

c++ - 为什么我可以通过返回类型推导从函数外部访问函数内部定义的结构?

c++ - 将 Boost 1_70_0 构建到 MS V Studio 2019 C++

c++ - 多态对象销毁和并发

c++ - Box2d cpp 给出 : box2d expression area > 1. 1 异常

c++ - 对临时对象的常量引用不会延长其生命周期

C++ 将强类型基类与 CRTP 和返回值类型推导混合

c++ - 类型名称 T::type::value 中的预期不合格 ID