I have a template<bool VAR> struct Obj
template declared in a header file (obj.h
) with explicit automatic move constructor (= 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>;
The member function of the template is defined in another file (obj.cpp
) with explicit instantiation of the template:
// obj.cpp
#include "obj.h"
template<bool VAR>
int Obj<VAR>::member_fun() const {
return 42;
}
template struct Obj<false>;
template struct Obj<true>;
This template is then used from the main file (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();
}
The .cpp
s are then compiled and linked together with the following Makefile
:
#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 $@
However, I get a linker error: undefined reference to 'Obj<true>::Obj(Obj<true>&&)'
-- the compiler apparently did not instantiate the constructor.
Obj<true>::member_fun()
is defined and the program indeed links successfully if I remove the reference to the move constructor from main.cpp
.
- If I remove
extern template
from the header, the program compiles.
- If I use
int
instead of std::vector<int>
for the type of member
, the program also compiles.
- cppreference.com claims that "the compiler will declare a move constructor as a non-explicit inline public member of its class". However, the manually defined
Obj(int)
constructor is also inline, but it is correctly instantiated.
(I received this error with Clang in a project that compiled fine with GCC, so I thought this was a Clang bug. However, when I reduced the problem to this simple case, both GCC 5.4.0 and Clang 3.8.0 produce the same results.)
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…