为什么通过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
类型制作例外?
是否只是为了避免标准中有太多例外?但我认为允许使用如上所述非常有益!还有什么我看不到的吗?
答案 0 :(得分:4)
但是,标准对例子(2)没有问题
因为在(2)的情况下,我们正在创建绑定到prvalue int const&
的{{1}}类型的临时。
但是42
不是左值,它是左值 - 因此我们不会尝试创建临时值,我们会尝试绑定到实际的对象。但编译器如何知道T::i
是一个你不想最终提供定义的左值,在这种情况下你真正的意思是构造一个临时的并复制它? T::i
不是该类型的一部分,constexpr
的类型只是i
。您可能不得不跳过很多障碍,甚至尝试提出一个可以正确豁免int const
但某些成员static constexpr int i
的措辞。
const int i
手动执行左值到右值的转换,并实现相同的目的。或者为+T::i
提供定义。
ODR规则足够复杂 - 您需要一个令人信服的理由在其中钻一个洞。
答案 1 :(得分:2)
假设在两个TU中发生相同的呼叫。函数check
可以取z
的地址,标准保证它在两次调用中都会看到相同的地址。
除了分配单个存储位置并将i
放在那里之外,您将如何实现这一目标?这几乎就是ODR所说的。