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.cpp
s 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.)