Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does it mean to "ODR-use" something?

This just came up in the context of another question.

Apparently member functions in class templates are only instantiated if they are ODR-used. Could somebody explain what exactly that means. The wikipedia article on One Definition Rule (ODR) doesn't mention "ODR-use".

However the standard defines it as

A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied.

in [basic.def.odr].

Edit: Apparently this is the wrong part and the entire paragraph contains multiple definitions for different things. This might be the relevant one for class template member function:

A non-overloaded function whose name appears as a potentially-evaluated expression or a member of a set of candidate functions, if selected by overload resolution when referred to from a potentially-evaluated expression, is odr-used, unless it is a pure virtual function and its name is not explicitly qualified.

I do however not understand, how this rule works across multiple compilation units? Are all member functions instantiated if I explicitly instantiate a class template?

like image 924
Sarien Avatar asked Oct 28 '13 08:10

Sarien


People also ask

What is an ODR use?

Court-related Online Dispute Resolution (ODR) is a public facing digital space in which parties can convene to resolve their dispute or case.

What is ODR violation?

In general, the ODR violation is defined as undefined behavior, which in practice means that if we have two different definitions of the same function (or a member function) in the program, compiler is free to chose any of them at any place the name is used.

What is ODR use C++?

The One Definition Rule (ODR) is an important rule of the C++ programming language that prescribes that objects and non-inline functions cannot have more than one definition in the entire program and template and types cannot have more than one definition by translation unit.


2 Answers

It's just an arbitrary definition, used by the standard to specify when you must provide a definition for an entity (as opposed to just a declaration). The standard doesn't say just "used", because this can be interpreted diversely depending on context. And some ODR-use doesn't really correspond to what one would normally associate with "use"; for example, a virtual function is always ODR-used unless it is pure, even if it isn't actually called anywhere in the program.

The full definition is in §3.2, second paragraph, although this contains references to other sections to complete the definition.

With regards to templates, ODR-used is only part of question; the other part is instantiation. In particular, §14.7 covers when a template is instantiated. But the two are related: while the text in §14.7.1 (implicit instantiation) is fairly long, the basic principle is that a template will only be instantiated if it is used, and in this context, used means ODR-used. Thus, a member function of a class template will only be instantiated if it is called, or if it is virtual and the class itself is instantiated. The standard itself counts on this in many places: the std::list<>::sort uses < on the individual elements, but you can instantiate a list over an element type which doesn't support <, as long as you don't call sort on it.

like image 86
James Kanze Avatar answered Sep 21 '22 04:09

James Kanze


In plain word, odr-used means something(variable or function) is used in a context where the definition of it must be present.

e.g.,

struct F {    static const int g_x = 2; };  int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed.                              // so it's OK without the definition of g_x  vector<int>  vi; vi.push_back( F::g_x );      // Error, this is odr-used, push_back(const int & t) expect                              // a const lvalue, so it's definition must be present 

Note, the above push_back passed in MSVC 2013, this behavior is not standard compliance, both gcc 4.8.2 and clang 3.8.0 failed, the error message is: undefined reference to F::g_x

like image 38
zhaorufei Avatar answered Sep 23 '22 04:09

zhaorufei