https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89311
Bug ID: 89311 Summary: Brace initialization needlessly invokes destructor Product: gcc Version: 8.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: raphael.kubo.da.costa at intel dot com Target Milestone: --- This is related to bug 85552 and bug 57082 as far as I can see. GCC and ICC fail to compile this (I'm using -std=gnu++14), whereas MSVC and clang accept it: #include <vector> template <class T> struct S { ~S() { for (size_t i = 0; i < sources_.size(); ++i) sources_[i]->frob(); } private: std::vector<T*> sources_; }; class C; struct T { S<C> s_{}; }; <source>: In instantiation of 'S<Source>::~S() [with T = C]': <source>:16:11: required from here <source>:7:20: error: invalid use of incomplete type 'class C' 7 | sources_[i]->frob(); | ~~~~~~~~~~~~~^~~~ <source>:13:7: note: forward declaration of 'class C' 13 | class C; | ^ which ends up requiring C to be fully declared before it can be used in T. I think https://bugs.llvm.org/show_bug.cgi?id=39363#c8 touches upon this in "The list-initialization case does not potentially-invoke the destructor in C++11 or C++14 either (unlike non-list copy-initialization, list-initialization directly executes a constructor on the destination object even in C++11, and as a result there is no temporary object created to trigger the potential invocation of a destructor). Clang gets that case right, but GCC has another bug there".