Construtor automático no modelo de classe explicitamente instanciado

eu tenho umtemplate<bool VAR> struct Obj modelo declarado em um arquivo de cabeçalho (obj.h) com construtor de movimentação automática 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>;

A função de membro do modelo é definida em outro arquivo (obj.cpp) com instanciação explícita do modelo:

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

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

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

Este modelo é usado no arquivo 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();
}

o.cpps são então compilados e vinculados com os seguintesMakefile:

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

No entanto, recebo um erro de vinculador:undefined reference to 'Obj<true>::Obj(Obj<true>&&)' - o compilador aparentemente não instancia o construtor.

Obj<true>::member_fun() é definido e o programa realmente é vinculado com êxito se eu remover a referência ao construtor move demain.cpp.Se eu removerextern template do cabeçalho, o programa é compilado.Se eu usarint ao invés destd::vector<int> para o tipo demember, o programa também compila.cppreference.com afirma que "o compilador declarará um construtor de movimentação como um não explícitona linha membro público de sua classe ". No entanto, o manual definidoObj(int) O construtor também está embutido, mas é instanciado corretamente.

(Eu recebi esse erro com o Clang em um projeto que foi compilado com o GCC, então achei que era um bug do Clang. No entanto, quando reduzi o problema a esse caso simples, o GCC 5.4.0 e o Clang 3.8.0 produzem o mesmo resultados.)

questionAnswers(3)

yourAnswerToTheQuestion