Die C++ 14 FD definiert is_constructible
wie folgt:
folgende Funktionsdeklaration Gegeben:
template <class T>
add_rvalue_reference_t<T> create() noexcept;
das Prädikat Bedingung für eine Template-Spezialisierung is_constructible<T, Args...>
erfüllt, wenn und nur dann, wenn Die folgende Variablendefinition wäre für einige erfundene Variable t
:
wohlgeformt 10
T t(create<Args>()...);
Zugriffskontrolle ist, als ob in einem Kontext, in keinem Zusammenhang mit T
und mit einem der Args
durchgeführt. Nur die Gültigkeit des unmittelbaren Kontextes von der Variableninitialisierung wird berücksichtigt. [ Hinweis: Die Auswertung der Initialisierung in Nebenwirkungen wie die Instanziierung der Klasse Vorlage Spezialisierungen und Funktionsschablone Spezialisierungen, die Erzeugung von implizit definierte Funktionen und so weiter führen kann. Solche Nebenwirkungen sind nicht im "unmittelbaren Kontext" und können dazu führen, dass das Programm schlecht ausgebildet ist. -Ende note]
Verringert nun die Frage im Wesentlichen zu „Ist die Destruktoraufrufs im unmittelbaren Kontext der Variableninitialisierung?“ [Klasse.dtor]/11:
wird implizit A destructor
- aufgerufen für ein konstruiertes Objekt mit statischer Speicherdauer (3.7.1) bei Programmende (3.6.3),
- für einen konstruierte Objekt mit automatischer Speicherdauer (3.7.3), wenn der Baustein, in dem ein Objekt erstellt wird, für ein aufgebautes temporäres Objekt (12.2) endet (6.7),
- .
In jedem Fall ist der Kontext des Aufrufs der Kontext der Konstruktion des Objekts.
So ist der destructor Aufruf ist im Zusammenhang mit dem Bau (was vermutlich auch ist hier die Initialisierung), was bedeutet, dass es in Betracht gezogen wird, und bewirkt, dass das Merkmal false
zurückzukehren.
Ich glaube, dass dies unterspezifiziert ist (z. B. sofortige vs nicht explizit-unmittelbaren Kontext?), Aber intuitiv erwarte ich eine konforme Implementierung, um den Ausdruck als schlecht gebildet - entweder SFINAE-freundlich oder nicht (vorzugsweise ersteres). Aber nie gut geformt.
Clang with libc++, libstdc++ and GCC do say that it's invalid, SFINAE-friendly.
Wenn ja, ist es eine Möglichkeit zu überprüfen, ob der Typ einen bestimmten Konstruktor hat, unabhängig von den Zugriffsbezeichner auf dem destructor?
Wie wäre es mit 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;
};
Demo. Konsistente Merkmale können leicht festgestellt werden: Nehmen Sie das is_only_constructible
Merkmal und kombinieren Sie es mit is_destructible
(deutlich Letzteres gibt false
in Kombination mit privaten Destruktoren).
In Verbindung stehend: https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/bPwd3UkZa6w – Caramiriel
@Caramiriel Leider adressiert es nicht direkt das Problem. 'is_destructible' hängt explizit von der Erreichbarkeit des Destruktors ab, was hier nicht der Fall ist. – Columbo