c++ - and - ¿Std:: piecewise_construct causa una violación de ODR?
constexpr in c++ (2)
En mi humilde opinión no hay conflicto bajo la ODR.
Un espacio de nombres sin nombre tiene el mismo efecto que marcar cosas para un enlace interno (estático). Esto realmente significa que cada TU usa sus propias definiciones únicas para tales tipos / funciones.
La forma en que los veo, cómo funcionan los marcadores de posición (:::: _ _ 1 y los sabores de la competencia), no es por instanciación sino por inferencia de tipo de tiempo de compilación:
_1, _2 etc. son simplemente marcadores de posición, y realmente no necesitan ser compatibles (los valores no tienen que pasar de una TU a otra, se pasan solo como parámetros de tipo inferido y, por lo tanto, su tipo real es inferido) Para tener la identity
de la TU actual.
IOW: Puedes definir fácilmente tus propios marcadores de posición al especializar algunos rasgos, y aún así deberían funcionar como un encanto.
namespace boost
{
template<int I> struct is_placeholder<
my_funny_own_placeholder_no_ODR_involved<I> >
{
enum _vt { value = I };
};
}
Supongo que la misma lógica podría ser válida para la construcción_unciones (pero no he visto tanto).
std::piecewise_construct
, definido en <utility>, tiene un enlace interno, ya que se declara constexpr
. Me pregunto si el uso de std::piecewise_construct
en un encabezado puede violar la ODR. Por ejemplo:
a.hpp
#include <utility>
#include <tuple>
struct point
{
point(int x, int y)
: x(x), y(y)
{}
int x, y;
};
inline std::pair<point, point> f(int x1, int y1, int x2, int y2)
{
return {
std::piecewise_construct,
std::forward_as_tuple(x1, y1), std::forward_as_tuple(x2, y2)
};
}
unidad de traducción 1
#include "a.hpp"
unidad de traducción 2
#include "a.hpp"
std::piecewise_construct
en f
en TU 1 se refiere a un objeto diferente al de f
en TU 2. Sospecho que f
infringe la ODR.
N3290 (probablemente ISO / IEC 14882: 2011 también) dice que el siguiente caso es una excepción de ODR, en 3.2 / 5:
un nombre puede referirse a un objeto const con enlace interno o sin vinculación si el objeto tiene el mismo tipo literal en todas las definiciones de D, y el objeto se inicializa con una expresión constante (5.19), y el valor (pero no la dirección) de el objeto se utiliza y el objeto tiene el mismo valor en todas las definiciones de D;
f
satisface casi todos los requisitos, pero "el valor (pero no la dirección) del objeto se usa" me parece ambiguo. Es cierto que std::piecewise_construct_t
no tiene estado, pero una llamada del constructor a trozos de std::pair
implica una llamada del constructor de copia declarada implícita de std::piecewise_construct_t
, cuyo argumento es const std::piecewise_construct_t &
. La dirección es "usada", ¿no es así?
Estoy muy desconcertado.
Referencia: http://lists.boost.org/Archives/boost/2007/06/123353.php
Parece que ya tienes tu respuesta en la publicación de la lista de correo. Sí, en mi opinión es un comportamiento indefinido o, al menos, un comportamiento definido no lo suficientemente claro.
Vea esta discusión de usenet para el mismo asunto que se discute.