Why is S::x not odr-used?

c++ one definition rule inline
odr rules
odr issue
cpp declaration
itself violates the c++ one definition rule
wikipedia one definition rule
static constexpr
member declaration c

Consider this example from cppreference:

struct S { static const int x = 1; };
void f() { &S::x; } // discarded-value expression does not odr-use S::x

I agree that &S::x is a discarded-value expression, since the standard says (9.2, paragraph 1 [stmt.expr] from n4700)

Expression statements have the form

expression-statement:
    expression_opt ;

The expression is a discarded-value expression (Clause 8)...

However, is that enough for S::x to not be odr-used? 6.2, paragraph 3 [basic.def.odr] states

A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless

  • ...
  • 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 (7.1) is applied to e, or
    • e is a discarded-value expression (Clause 8).

The problem is that the discarded-value expression &S::x has no potential results (which means that S::x is not a potential result of &S::x), as you can see from 6.2, paragraph 2 [basic.def.odr]:

... The set of potential results of an expression e is defined as follows:

  • If e is an id-expression (8.1.4), the set contains only e.
  • If e is a subscripting operation (8.2.1) with an array operand, the set contains the potential results of that operand.
  • ...
  • Otherwise, the set is empty.

Then, how can you explain that S::x is not odr-used?


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

Definitions and ODR (One Definition Rule), struct S { int n; // defines S::n static int i; // declares, but doesn't define S::i inline (1, S::x) // S::x is not odr-used here : f(S::x); // S::x is odr-used here: a definition is  name lookup from within each definition finds the same entities (after overload-resolution), except that constants with internal or no linkage may refer to different objects as long as they are not ODR-used and have the same values in every definition. overloaded operators, including conversion, allocation,


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;

[basic.def.odr], struct S { static const int x = 0; }; const int &f(const int &r); int n = b ? (1, S::x) // S​::​​x is not odr-used here : f(S::x); // S​::​x is odr-used here, so a definition is  And neither would I. you wouldn’t believe me. id End up in a lie. It shouldn’t be easy. There’s no wrong or right. And you’re the one who started it yeah yeah. you thought you found love


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.

When is a variable odr-used in C++14?, (1, S::x) // S​::​x is not odr-used here : f(S::x); // S​::​x is odr-used here, so a definition is required — end example. ] — end note. ] 3. #. A function is named by​  A virtual member function is odr-used if it is not pure. A function is odr-used if it is named by a potentially-evaluated expression or conversion . A non-placement allocation or deallocation function for a class is odr-used by the definition of a constructor of that class .


Definitions and ODR, return x ? S::a : S::b; }. By the rules of C++11 the variables named by S::a and S::b are odr-used, since the lvalue-to-rvalue conversion is not  Online dispute resolution (ODR) is a branch of dispute resolution which uses technology to facilitate the resolution of disputes between parties. It primarily involves negotiation , mediation or arbitration , or a combination of all three.


One Definition Rule, int f(int x); // declares, but doesn't define f and x int f(int x) { // defines f and x return struct S { // defines S int n; // defines S::n static int i; // declares, but doesn't definition of every non-inline function or variable that is odr-used (see below) is  I working on implementing a PDM system, and I think we should use straight alpha Revisions, and not skip any letters. The opposing side wants to follow the ASME guidelines and skip I, O, Q, S, X and Z. I would be more satisfied with this if someone gave me some good arguments on why this is so important.


The compiler seems to be allocating storage for the variable S::x , The One Definition Rule (ODR) is an important rule of the C++ programming language that In the entire program, an object or non-inline function cannot have more than one In the following, forming a pointer to S or defining a function taking a const int N = 10; }; char data[C::N]; // N "used" without out-of-​class definition. 50+ videos Play all Mix - S-X - Still I Get (Official Music Video) YouTube; S-X - Show Me Love (Official Audio) - Duration: 3:50. S-X 845,147 views. 3:50.