c++ templates one-definition-rule

c++ - ¿Qué significa "usar ODR" algo?



templates one-definition-rule (2)

En palabras simples, odr-used significa que algo (variable o función) se usa en un contexto donde la definición de este debe estar presente.

p.ej,

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

Tenga en cuenta que el push_back anterior pasó en MSVC 2013, este comportamiento no es estándar, tanto gcc 4.8.2 como clang 3.8.0 fallaron, el mensaje de error es: referencia no definida a `K :: g_x ''

Esto acaba de surgir en el contexto de otra pregunta .

Aparentemente, las funciones miembro en las plantillas de clase solo se instancian si se usan ODR. ¿Podría alguien explicar qué significa exactamente eso? El artículo de wikipedia sobre la regla de una definición (ODR) no menciona el " uso de ODR ".

Sin embargo, el estándar lo define como

Una variable cuyo nombre aparece como una expresión potencialmente evaluada se utiliza odr a menos que sea un objeto que satisfaga los requisitos para aparecer en una expresión constante (5.19) y la conversión lvalue-a-rvalue (4.1) se aplique inmediatamente.

en [basic.def.odr].

Editar: aparentemente esta es la parte incorrecta y todo el párrafo contiene múltiples definiciones para diferentes cosas. Esta podría ser la relevante para la función de miembro de plantilla de clase:

Una función no sobrecargada cuyo nombre aparece como una expresión potencialmente evaluada o un miembro de un conjunto de funciones candidatas, si se selecciona mediante resolución de sobrecarga cuando se hace referencia a una expresión potencialmente evaluada, se usa odr, a menos que sea una virtual pura función y su nombre no está explícitamente calificado.

Sin embargo, no entiendo cómo funciona esta regla en varias unidades de compilación. ¿Se crean instancias de todas las funciones miembro si explícito una instancia de una plantilla de clase?


Es solo una definición arbitraria, utilizada por el estándar para especificar cuándo debe proporcionar una definición para una entidad (en lugar de solo una declaración). El estándar no dice solo "usado", porque esto puede interpretarse de manera diversa según el contexto. Y el uso de ODR no se corresponde realmente con lo que normalmente se asocia con el "uso"; por ejemplo, una función virtual siempre se usa con ODR a menos que sea pura, incluso si en realidad no se llama a ninguna parte del programa.

La definición completa está en §3.2 , segundo párrafo, aunque contiene referencias a otras secciones para completar la definición.

Con respecto a las plantillas, ODR-used es solo una parte de la pregunta; la otra parte es ejemplificación. En particular, §14.7 cubre cuando se crea una instancia de una plantilla. Pero los dos están relacionados: mientras que el texto en §14.7.1 (instanciación implícita) es bastante largo, el principio básico es que una plantilla solo se instanciará si se usa, y en este contexto, usado significa ODR-usado. Por lo tanto, una función miembro de una plantilla de clase solo se creará una instancia si se llama, o si es virtual y la clase misma se crea una instancia. El estándar en sí mismo cuenta con esto en muchos lugares: std::list<>::sort usa < en los elementos individuales, pero puede instanciar una lista sobre un tipo de elemento que no admite < , siempre que no lo haga t llamar a sort en él.