FD C++14 определяет is_constructible
следующим образом:
Учитывая следующее объявление функции:
template <class T>
add_rvalue_reference_t<T> create() noexcept;
предикатное условие для специализации шаблона is_constructible<T, Args...>
должно быть выполнено тогда и только тогда, когда следующее определение переменной будет корректным для некоторой придуманной переменной t
:
T t(create<Args>()...);
Проверка доступа выполняется, как будто в контексте, не связанном с T
и любым из Args
. Учитывается только правильность непосредственного контекста инициализации переменной. [ Примечание: оценка инициализации может привести к побочным эффектам, таким как создание экземпляров специализаций шаблонов классов и специализаций шаблонов функций. , генерация неявно определенных функций и так далее. Такие побочные эффекты не относятся к «непосредственному контексту» и могут привести к неправильному построению программы. —конец примечания ]
Теперь вопрос по существу сводится к «Находится ли вызов деструктора в непосредственном контексте инициализации переменной?» [класс.дтор]/11:
Деструктор вызывается неявно
- для построенного объекта со статической продолжительностью хранения (3.7.1) при завершении программы (3.6.3),
- для сконструированного объекта с автоматической продолжительностью хранения (3.7.3) при выходе из блока, в котором создается объект (6.7),
- для построенного временного объекта, когда его время жизни заканчивается (12.2).
В каждом случае контекст вызова является контекстом построения объекта.
Таким образом, вызов деструктора находится в контексте конструкции (которая предположительно является синонимом инициализации здесь), что подразумевает, что он рассматривается, и приводит к тому, что трейт возвращает false
. явно-непосредственный контекст?), но интуитивно я ожидаю, что соответствующая реализация пометит выражение NotDestructible()
как неправильно сформированное - либо дружественное к SFINAE, либо нет (предпочтительно первое). Однако никогда не был правильно сформирован.
Clang с libc++, libstdc++ и GCC действительно говорят, что это недопустимо, Подходит для SFINAE.
Если да, то есть ли способ проверить, имеет ли тип конкретный конструктор, независимо от спецификатора доступа в деструкторе?
Как насчет использования new
?
template <typename T, typename... Args>
class is_only_constructible
{
template <typename, typename=void> struct test : std::false_type {};
template <typename U>
struct test<U, decltype(void(new U(std::declval<Args>()...)))> : std::true_type {};
public:
static constexpr bool value = test<T>::value;
};
Демо. Непротиворечивые трейты можно легко установить: возьмите трейт is_only_constructible
и объедините его с is_destructible
(очевидно, что последний возвращает false
в сочетании с приватными деструкторами).
person
Columbo
schedule
22.01.2015
is_destructible
явно зависит от доступности деструктора, что здесь не так. - person Columbo   schedule 22.01.2015