简体   繁体   中英

Why does one-definition-rule-use (odr-use) depend on the context?

Given the following piece of code:

#include <iostream>

struct A {
    static constexpr float a = 2.0f;
};

// non-const reference to make it more explicit - same behaviour
template<class T> constexpr inline T square(T& x)
{
    return x * x;
}

int main() {
    /*constexpr*/ float val = square(A::a);
    std::cout << val;
}

This program fails to link with undefined reference to 'A::a' (always with clang, only on -O0 with g++), however it links properly if I uncomment the constexpr from the val declaration.

So far I understand that constexpr can't be odr-used without explicit definition in one of the unit files, but I don't understand why does it work while assigning to the constexpr .

It seems like those two cases are handled differently depending on the context. But why? Shouldn't the compiler just evaluate this function at compile time in both cases?

Why does odr-use depend on the context?

It doesn't. square(A::a) odr-uses A::a , period.

Most ODR violations, however, are not required to be diagnosed, and this is no exception.

Shouldn't the compiler just evaluate this function at compile time in both cases?

The initializer of a constexpr variable must be evaluated at compile time. (Well, not quite, but the compiler must be evaluate it to the point where it can determine that it is a valid constant expression, at which point it might as well just do the whole thing.) For a non- constexpr local variable, there's no such guarantee.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM