Ответ 1
Похоже, что у вас уже есть свой ответ в этом списке рассылки по рассылке. Да, по-моему, это поведение undefined или, по крайней мере, недостаточно четко определенное поведение.
См. это обсуждение Usenet для обсуждения того же вопроса.
'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
Похоже, что у вас уже есть свой ответ в этом списке рассылки по рассылке. Да, по-моему, это поведение undefined или, по крайней мере, недостаточно четко определенное поведение.
См. это обсуждение Usenet для обсуждения того же вопроса.
ИМХО, в ODR нет конфликта.
Неименованное пространство имен имеет тот же эффект, что и для внутренней привязки (статический). Это действительно означает, что каждый TU использует свои собственные уникальные определения для таких типов/функций.
То, как я смотрю на них, как заполнители (:: _ 1 и конкурирующие ароматы) работают, не по экземпляру, а по умозаключению типа compiletime:
_1, _2 и т.д. являются просто заполнителями, и им действительно не нужно быть совместимыми (значения не должны передаваться от одного ТУ к другому, они передаются только как параметры типа вывода и как таковые их фактические тип выводится как identity
из текущего TU).
IOW: вы можете легко определить свои собственные заполнители, специализируясь на некоторых чертах, и они все равно должны работать как шарм.
namespace boost
{
template<int I> struct is_placeholder<
my_funny_own_placeholder_no_ODR_involved<I> >
{
enum _vt { value = I };
};
}
Я полагаю, что одна и та же логика могла бы выполняться для кусочной_конструкции (но я не так много смотрел).