Automatischer Konstruktor in explizit instanziierter Klassenvorlage

Ich habe eintemplate<bool VAR> struct Obj template deklariert in einer Header-Datei obj.h) mit explizitem Konstruktor für automatische Verschiebung = default).

// obj.h
#pragma once
#include <vector>

template<bool VAR>
struct Obj {
  std::vector<int> member;
  Obj(int m): member(m) { }
  Obj(Obj&&) = default;
  int member_fun() const;
};

extern template struct Obj<false>;
extern template struct Obj<true>;

Die Mitgliedsfunktion der Vorlage ist in einer anderen Datei definiert obj.cpp) mit expliziter Instanziierung der Vorlage:

// obj.cpp
#include "obj.h"

template<bool VAR>
int Obj<VAR>::member_fun() const {
  return 42;
}

template struct Obj<false>;
template struct Obj<true>;

Diese Vorlage wird dann aus der Hauptdatei verwendet main.cpp):

// main.cpp
#include <utility>
#include "obj.h"

int main() {
  Obj<true> o1(20);
  Obj<true> o2(std::move(o1));
  return o2.member_fun();
}

Das.cpps werden dann kompiliert und mit dem folgenden @ verknüpMakefile:

#CXX=clang++
CXX=g++
CXXFLAGS=-Wall -Wextra -std=c++14

a.out: obj.o main.o
    $(CXX) $(CXXFLAGS) $^ -o a.out

obj.o: obj.cpp obj.h
    $(CXX) $(CXXFLAGS) -c 
#CXX=clang++
CXX=g++
CXXFLAGS=-Wall -Wextra -std=c++14

a.out: obj.o main.o
    $(CXX) $(CXXFLAGS) $^ -o a.out

obj.o: obj.cpp obj.h
    $(CXX) $(CXXFLAGS) -c $< -o $@
main.o: main.cpp obj.h
    $(CXX) $(CXXFLAGS) -c $< -o $@
lt; -o $@ main.o: main.cpp obj.h $(CXX) $(CXXFLAGS) -c
#CXX=clang++
CXX=g++
CXXFLAGS=-Wall -Wextra -std=c++14

a.out: obj.o main.o
    $(CXX) $(CXXFLAGS) $^ -o a.out

obj.o: obj.cpp obj.h
    $(CXX) $(CXXFLAGS) -c $< -o $@
main.o: main.cpp obj.h
    $(CXX) $(CXXFLAGS) -c $< -o $@
lt; -o $@

Ich erhalte jedoch einen Linker-Fehler:undefined reference to 'Obj<true>::Obj(Obj<true>&&)' - Der Compiler hat den Konstruktor anscheinend nicht instanziiert.

Obj<true>::member_fun() ist definiert und das Programm verlinkt tatsächlich erfolgreich, wenn ich den Verweis auf den move-Konstruktor von @ entfermain.cpp.Wenn ich entferneextern template Aus der Kopfzeile wird das Programm kompiliert.Wenn ich @ benutint Anstatt vonstd::vector<int> für den Typ vonmember, das Programm wird auch kompiliert. cppreference.com behauptet, dass "der Compiler einen move -Konstruktor als nicht explizites @ deklariein der Reih public Mitglied seiner Klasse ". Das manuell definierteObj(int)er Konstruktor @ ist ebenfalls inline, wird jedoch korrekt instanziiert.

(Ich habe diesen Fehler mit Clang in einem Projekt erhalten, das mit GCC einwandfrei kompiliert wurde. Daher dachte ich, dass dies ein Clang-Fehler ist. Als ich das Problem jedoch auf diesen einfachen Fall reduzierte, produzierten sowohl GCC 5.4.0 als auch Clang 3.8.0 das gleiche Ergebnisse.)

Antworten auf die Frage(6)

Ihre Antwort auf die Frage