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

Reply via email to