ODR使用行为的基本原理

ODR-usage behaviour rationale

本文关键字:ODR      更新时间:2023-10-16

为什么通过const引用传递参数总是意味着使用了ODR?我理解,因为标准是这样定义的,但为什么它不例外,至少对积分常数是这样?

例如(我自己的例子来自几个小时前的答案):

struct T {
    static constexpr int i = 42;
};
void check(const int& z);
int main() {
    check(T::i); // <- 1
    check(42); // <- 2
}

线路(1)将在链路时触发一个错误-标准认为它是使用T::i的ODR,并且看不到定义。然而,标准对示例(2)没有问题。既然(2)必须工作,为什么(1)不能为内部constexpr工作?我意识到,通常您需要获取对象的地址来通过引用传递它,但在数字文本的情况下肯定不是这样。为什么标准不为某些constexpr类型制定例外?

这仅仅是为了避免标准中有太多的例外吗?但我认为允许使用上述内容是非常有益的!还有什么我看不见的吗?

然而,标准对示例(2)没有问题

因为在(2)的情况下,我们正在创建一个类型为int const&临时,它绑定到prvalue 42

但是T::i不是一个右值,它是一个左值——所以我们不会试图创建一个临时的,我们会尝试绑定到实际的对象。但是编译器如何知道T::i是一个你不想最终为其提供定义的左值,在这种情况下,你真正的意思是构建一个临时的并复制它?constexpr不是类型的一部分,i的类型只是int const。你可能需要跨越大量的障碍,甚至试图想出一个措辞来正确地豁免你的static constexpr int i,但某些成员const int i

都是为了解决什么问题?您可以通过+T::i手动执行左值到右值的转换,并实现同样的效果。或者提供T::i的定义。

ODR规则已经足够复杂了——你需要一个令人信服的理由在其中钻一个洞。

假设同一个调用发生在两个TU中。函数check可以采用z的地址,并且标准保证它在两个调用中看到相同的地址。

除了分配一个存储位置并将i放在那里之外,您将如何实现这一点?这几乎就是ODR所说的。

相关文章:
  • 没有找到相关文章