Constructor automático en plantilla de clase explícitamente instanciada

tengo untemplate<bool VAR> struct Obj plantilla declarada en un archivo de encabezado (obj.h) con el constructor de movimiento automático explícito (= 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>;

La función miembro de la plantilla se define en otro archivo (obj.cpp) con instanciación explícita de la plantilla:

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

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

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

Esta plantilla se usa desde el archivo principal (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();
}

los.cppluego se compilan y se vinculan con lo siguienteMakefile:

#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 $@

Sin embargo, recibo un error de vinculador:undefined reference to 'Obj<true>::Obj(Obj<true>&&)' - el compilador aparentemente no creó una instancia del constructor.

Obj<true>::member_fun() está definido y el programa se vincula con éxito si elimino la referencia al constructor de movimiento demain.cpp.Si quitoextern template desde el encabezado, el programa compila.Si yo usoint en lugar destd::vector<int> para el tipo demember, el programa también compila.cppreference.com afirma que "el compilador declarará un constructor de movimiento como no explícitoen línea miembro público de su clase ". Sin embargo, el definido manualmenteObj(int) El constructor también está en línea, pero está correctamente instanciado.

(Recibí este error con Clang en un proyecto que compiló bien con GCC, así que pensé que era un error de Clang. Sin embargo, cuando reduje el problema a este simple caso, tanto GCC 5.4.0 como Clang 3.8.0 producen lo mismo resultados.)

Respuestas a la pregunta(3)

Su respuesta a la pregunta