'std:: piecewise_construct', определенный в <utility> , имеет внутреннюю связь, поскольку он объявлен constexpr. Интересно, может ли использование "std:: piecewise_construct" в заголовке нарушить ODR. Например:
// 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"
"std:: piecewise_construct" в "f" в TU 1 относится к другому объекту, чем к "f" в TU 2. Я подозреваю, что "f" нарушает ODR.
N3290 (вероятно, ISO/IEC 14882: 2011 также) говорит, что следующий случай является исключением ODR, в 3.2/5:
имя может ссылаться на объект const с внутренней или никакой связью, если объект имеет одинаковый тип литерала во всех определениях D, и объект инициализируется константным выражением (5.19), а значение (но не адрес) объекта, и объект имеет то же значение во всех определениях D;
'f' удовлетворяет почти всем требованиям, но "используется значение (но не адрес) объекта" кажется мне неоднозначным. Это правда, что "std:: piecewise_construct_t" не имеет состояния, но вызов кусочного конструктора "std:: pair" включает вызов конструктора с неявным объявлением копии "std:: piecewise_construct_t", аргументом которого является "const std:: piecewise_construct_t & '. Адрес" используется", не так ли?
Я очень озадачен.
Ссылка: http://lists.boost.org/Archives/boost/2007/06/123353.php