std::piecewise_construct
, defined in <utility>, has internal linkage since it is declared constexpr
. I wonder if use of std::piecewise_construct
in a header can violate ODR. For example:
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)
};
}
translation unit 1
#include "a.hpp"
translation unit 2
#include "a.hpp"
The std::piecewise_construct
in f
in TU 1 refers to a different object than that in f
in TU 2. I suspect f
violates ODR.
N3290 (probably ISO/IEC 14882:2011 also) says the following case is an exception of ODR, in 3.2/5:
a name can refer to a const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression (5.19), and the value (but not the address) of the object is used, and the object has the same value in all definitions of D;
f
satisfies almost all the requirements, but "the value (but not the address) of the object is used" seems ambiguous to me. It's true that std::piecewise_construct_t
has no state, but a call of the piecewise constructor of std::pair
involves a call of the implicit-declared copy constructor of std::piecewise_construct_t
, whose argument is const std::piecewise_construct_t &
. The address is "used", isn't it?
I'm very puzzled.
Reference: http://lists.boost.org/Archives/boost/2007/06/123353.php