7

Entstanden aus this Codereview Thema:std :: is_constructible gibt nicht das richtige Ergebnis

#include <cstddef> 
#include <algorithm> 
#include <iostream> 
#include <type_traits> 
#include <utility> 

template <typename T> 
class aggregate_wrapper : public T { 
private: 
    using base = T; 

public: 
    using aggregate_type = T; 

    template <typename... Ts> 
    aggregate_wrapper(Ts&&... xs) 
     : base{std::forward<Ts>(xs)...} { 
    // nop 
    } 
}; 

struct foo_t { 
    foo_t(int) {} 
}; 

int main() { 
    std::cout << std::is_constructible<foo_t>::value << std::endl; 
    std::cout << std::is_constructible<aggregate_wrapper<foo_t>>::value << std::endl; 
    // aggregate_wrapper<foo_t> v; // won't compile 
} 

Wie konnte std::is_constructible<aggregate_wrapper<foo_t>>::value wahr sein, wenn aggregate_wrapper<foo_t> v; eigentlich nicht kompilieren?

+0

Vielleicht machst du mental * constructible * mit * default construcible *? Ein 'aggregate_wrapper ' kann sicherlich konstruiert werden, nur nicht über 'aggregate_wrapper v;'. –

+0

@ M.M Nein, 'is_default_constructible ' und 'is_constructible ' (was bedeutet, dass 'Args ...' ist eine leere Packung) sind gleichwertig. –

+0

Nicht sicher, warum das wieder geöffnet wurde; die dup ist direkt am point. –

Antwort

2

In dem C++ Standard in der is_constructible Beschreibung, gibt es dieses unschuldig aussehendes Zitat:

Nur die Gültigkeit des unmittelbaren Kontextes der [imaginären v] Variableninitialisierung betrachtet wird.

Und dann eine Notiz zu erklären, was es bedeutet:

Die Auswertung der Initialisierung in Seiten Effekte wie die Instanziierung der Klasse Template Spezialisierungen und Funktions-Template Spezialisierungen, die Generation implizit zur Folge haben kann definierte Funktionen und so weiter. Solche Nebenwirkungen sind nicht in dem unmittelbaren Kontext und können dazu führen, dass das Programm schlecht gebildet wird.

Meine Interpretation ist, dass, wenn Sie schreiben:

aggregate_wrapper<foo_t> v; 

Sie den Standardkonstruktor von aggregate_wrapper verwenden, es existiert, und es ist zu erreichen, so dass es gelingt, zumindest in dem unmittelbaren Kontext. Dann enthält der nicht-unmittelbare Kontext den Rumpf des Konstruktors, und das schlägt fehl, aber das ändert das Ergebnis von is_constructible nicht.

+0

Dann denke ich, 'std :: is_constructible' ist sowieso nicht so nützlich. Würde lieber selbst einen schreiben, der über diesen unmittelbaren Kontext hinausgeht. – Lingxi

+0

Die eigentliche Frage sollte sein, warum 'std :: is_constructible' im' unmittelbaren Kontext' aufhört? – Lingxi

Verwandte Themen