Why is S::x not odr-used?

谁说我不能喝 提交于 2019-11-29 22:05:11

It is indeed odr-used. Your analysis is correct (and I fixed that example a while ago).

Yes, in the example, &S::x odr-uses S::x.

[basic.def.odr]/4

A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion to x yields a constant expression that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion is applied to e, or e is a discarded-value expression.

The address of an object is never a constant expression. That's why S::x is odr-used in &S::x.

To justify that last assertion:

[expr.const]/6

A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints [...]

and

[expr.const]/2.7

2) An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:
[...]
2.7) an lvalue-to-rvalue conversion unless it is applied to

(none of the following points applies:)

2.7.1) a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile const object with a preceding initialization, initialized with a constant expression, or
2.7.2) a non-volatile glvalue that refers to a subobject of a string literal, or
2.7.3) a non-volatile glvalue that refers to a non-volatile object defined with constexpr, or that refers to a non-mutable subobject of such an object, or
2.7.4) a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e;

When declaring const int, it may be entirely discarded by the compiler unless you using its address. taking the address is not enough.

Discarded is not mean the value is not evaluated, it is, but it mean there is no memory address containing the const value, the compiler just replace the const variable by its value, as it was just a macro.

In addition, when taking a pointer to it and taking back the value from the pointer, doesn't impress the compiler much, it just ignores it and use the value.

The following code shows it, this code can be compiled and run (I test it by several compilers, I'm still not sure if it successfully compiled by all...) despite of the fact that S::x was not declared:

#include <iostream>
using namespace std;
struct S
{
    static const int x=0; 
};
//const int S::x; //discarded
int main()
{
    const int *px = &S::x;  //taking the address
    cout<< *px <<endl; //print the value - OK
    return 0;
}

But if I'll try to use the address itself(not the value) like:

cout<< px <<endl; //print the address - Will be failed

the link will failed dou to: "undefined reference to S::x".

Therefore, my conclusion is: taking an address without using it, doesn't count at all.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!