Рассмотрим эту программу в трех файлах:
// 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() {
}
с a.cpp
и main.cpp
, скомпилированными как единицы перевода. Я думаю, что определение g
должно быть нарушением ODR, потому что f()
может иметь значение 1
или 3
, тем самым изменяя тип возвращаемого значения g()
и то, что он будет выводить на std::cout
.
Однако все имена в определении после поиска имен и разрешения перегрузки ссылаются на одни и те же объекты в каждой единице перевода, которая включает a.h
, поэтому я не вижу, какое из требований ODR нарушается.
Не нарушает ли программа правило одного определения. Если да, то какая именно часть нарушена?