Ответ 1
С++ 14 FD определяет is_constructible
следующим образом:
Учитывая следующее объявление функции:
template <class T> add_rvalue_reference_t<T> create() noexcept;
условие предиката для типовой специализации
is_constructible<T, Args...>
должно выполняться тогда и только тогда, когда следующее определение переменной будет хорошо сформировано для некоторых изобретенных переменнаяt
:T t(create<Args>()...);
Проверка доступа выполняется как в контексте, не связанном с
t
и любой изArgs
. Только справедливость контекста рассматривается переменная инициализация. [Примечание: оценка инициализации может привести к побочным эффектам, таким как создание шаблонов шаблонов шаблонов и шаблонов функций специализация, генерация неявно определенных функций и скоро. Такие побочные эффекты не находятся в "непосредственном контексте" и могут приводят к плохой форме программы. -end note]
Теперь вопрос существенно сводится к "Является ли вызов деструктора в непосредственном контексте инициализации переменной?" [Class.dtor]/11:
Деструктор вызывается неявно
- для построенного объекта со статической продолжительностью хранения (3.7.1) при завершении программы (3.6.3),
- для построенного объекта с автоматической продолжительностью хранения (3.7.3), когда блок, в котором создается объект, завершает (6.7),
- для созданного временного объекта, когда его время жизни заканчивается (12.2).
В каждом случае контекст вызова - это контекст построение объекта.
Таким образом, вызов деструктора находится в контексте конструкции (которая, по-видимому, является синонимом инициализации здесь), что подразумевает, что она рассматривается и заставляет черту возвращаться false
.
Я полагаю, что это недоказано (например, немедленный или неявно-непосредственный контекст?), Но интуитивно я ожидаю, что соответствующая реализация будет отмечать выражение NotDestructible()
как плохо сформированное - либо SFINAE-дружественное, либо нет (желательно первое). Тем не менее, он не был хорошо сформирован.
Clang с libС++, libstdС++ и GCC говорят, что он недействителен, SFINAE-friendly.
Если да, есть ли способ проверить, имеет ли тип конкретный конструктор, независимо от спецификатора доступа на деструкторе?
Как насчет использования 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
в сочетании с частными деструкторами).