https://gcc.gnu.org/bugzilla/show_bug.cgi?id=76521
Bug ID: 76521 Summary: Explicit template instantiation suppresses defaulted inline move constructor Product: gcc Version: 6.1.1 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: rustamabd at gmail dot com Target Milestone: --- Created attachment 39434 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39434&action=edit test case.cpp It seems that an explicitly defaulted constructors are sometimes suppressed by the declaration of an explicitly instantiated template. As in this example: #include <vector> template<bool VAR> struct Obj { std::vector<int> member; Obj() { } Obj(Obj&&) = default; }; extern template struct Obj<true>; int main() { Obj<true> o1; Obj<true> o2(std::move(o1)); } template struct Obj<true>; Command line: g++ -std=c++14 a.cpp Error message: a.cpp:(.text+0x34): undefined reference to `Obj<true>::Obj(Obj<true>&&)' I believe this is a bug because: 1) [dcl.fct.def.default]/5: "A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted." 2) class.mfct]/1: "A member function may be defined ([dcl.fct.def]) in its class definition, in which case it is an inline member function ([dcl.fct.spec])" So the move-constructor is definitely "inline". Then we have: 3) [temp.explicit]/10: "Except for inline functions and variables, ..., explicit instantiation declarations have the effect of suppressing the implicit instantiation of the entity to which they refer. [ Note: The intent is that an inline function that is the subject of an explicit instantiation declaration will still be implicitly instantiated when odr-used ([basic.def.odr]) so that the body can be considered for inlining, but that no out-of-line copy of the inline function would be generated in the translation unit. — end note ]" So, the move-constructor should not have been suppressed by "extern template struct Obj<true>". Interestingly, any optimization level other than O0 makes the error go away: g++ -std=c++14 -O1 a.cpp - no errors