未指定的常量表达式值和ODR



在三个文件中考虑这个程序:

// a.h
#include<iostream>
constexpr auto f() {
int i = 0;
auto l1 = [](int& j) { return ++j; };
auto l2 = [](int& j) { return j*=2; };
return l1(i) + l2(i);
}
template<auto V> struct constant {};
inline auto g() {
constexpr auto x = f();
std::ios_base::Init init; // Avoid possible initialization order issues
std::cout << x;
return constant<x>{};
}
static auto x = g();
inline auto y = g();
// a.cpp
#include "a.h"
// main.cpp
#include "a.h"
int main() {
}

其中CCD_ 1和CCD_。我认为g的定义应该是ODR冲突,因为f()可以计算为13,从而更改g()的返回类型以及它将向std::cout输出的内容。

然而,在名称查找和重载解析之后,定义中的所有名称都将引用包括a.h的每个翻译单元中的相同实体,因此我看不出违反了ODR要求中的哪一个。

程序是否违反了一个定义规则。如果是,具体违反了哪一部分?

[basic.def.odr]/6状态:

[…]如果a.cpp0的定义满足所有这些要求,那么行为就好像存在D的单个定义一样。[…]

整个程序的行为必须像只有一个g副本一样。这意味着,当两个翻译单元被单独编译时,实现(以某种方式(必须确保它不会做任何会使g的两个副本彼此不可互换的事情,例如为f()计算两个不同的值。在任何其他情况下,允许实现在某些调用中将f()求值为1,在其他调用中求值为3(尽管实际实现不太可能做到这一点(,但在这种特殊情况下,它必须确保两个调用返回相同的值。

相关内容

  • 没有找到相关文章

最新更新