Reputation: 60058
I'm trying to compile with explicit template instatiation only.
Consider this dummy snippet
#include <vector>
template struct std::allocator<int>;
template struct std::vector<int, std::allocator<int>>;
void fun(){
std::vector<int> v;
}
int main (){
fun();
};
I would like to compile it with
g++ -std=c++11 -fno-implicit-templates fun.cc
I expected this to work, however it complains of unresolved references to std::vector
member functions. Shouldn't member functions be automatically instantiated along with the std::vector
class? How can I make it work?
The compiler error is:
/tmp/cc1QxQUn.o: In function `std::vector<int, std::allocator<int> >::push_back(int const&)':
vec.cc:(.text._ZNSt6vectorIiSaIiEE9push_backERKi[_ZNSt6vectorIiSaIiEE9push_backERKi]+0x65): undefined reference to `void std::vector<int, std::allocator<int> >::_M_emplace_back_aux<int const&>(int const&)'
/tmp/cc1QxQUn.o: In function `std::vector<int, std::allocator<int> >::push_back(int&&)':
vec.cc:(.text._ZNSt6vectorIiSaIiEE9push_backEOi[_ZNSt6vectorIiSaIiEE9push_backEOi]+0x2a): undefined reference to `void std::vector<int, std::allocator<int> >::emplace_back<int>(int&&)'
/tmp/cc1QxQUn.o: In function `std::vector<int, std::allocator<int> >::insert(__gnu_cxx::__normal_iterator<int const*, std::vector<int, std::allocator<int> > >, int const&)':
vec.cc:(.text._ZNSt6vectorIiSaIiEE6insertEN9__gnu_cxx17__normal_iteratorIPKiS1_EERS4_[_ZNSt6vectorIiSaIiEE6insertEN9__gnu_cxx17__normal_iteratorIPKiS1_EERS4_]+0x14d): undefined reference to `void std::vector<int, std::allocator<int> >::_M_insert_aux<int>(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int&&)'
vec.cc:(.text._ZNSt6vectorIiSaIiEE6insertEN9__gnu_cxx17__normal_iteratorIPKiS1_EERS4_[_ZNSt6vectorIiSaIiEE6insertEN9__gnu_cxx17__normal_iteratorIPKiS1_EERS4_]+0x166): undefined reference to `void std::vector<int, std::allocator<int> >::_M_insert_aux<int const&>(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&)'
/tmp/cc1QxQUn.o: In function `std::vector<int, std::allocator<int> >::insert(__gnu_cxx::__normal_iterator<int const*, std::vector<int, std::allocator<int> > >, int&&)':
vec.cc:(.text._ZNSt6vectorIiSaIiEE6insertEN9__gnu_cxx17__normal_iteratorIPKiS1_EEOi[_ZNSt6vectorIiSaIiEE6insertEN9__gnu_cxx17__normal_iteratorIPKiS1_EEOi]+0x32): undefined reference to `__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > std::vector<int, std::allocator<int> >::emplace<int>(__gnu_cxx::__normal_iterator<int const*, std::vector<int, std::allocator<int> > >, int&&)'
/tmp/cc1QxQUn.o: In function `void std::vector<int, std::allocator<int> >::_M_assign_dispatch<int const*>(int const*, int const*, std::__false_type)':
vec.cc:(.text._ZNSt6vectorIiSaIiEE18_M_assign_dispatchIPKiEEvT_S5_St12__false_type[_ZNSt6vectorIiSaIiEE18_M_assign_dispatchIPKiEEvT_S5_St12__false_type]+0x2d): undefined reference to `void std::vector<int, std::allocator<int> >::_M_assign_aux<int const*>(int const*, int const*, std::forward_iterator_tag)'
/tmp/cc1QxQUn.o: In function `void std::vector<int, std::allocator<int> >::_M_insert_dispatch<int const*>(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const*, int const*, std::__false_type)':
vec.cc:(.text._ZNSt6vectorIiSaIiEE18_M_insert_dispatchIPKiEEvN9__gnu_cxx17__normal_iteratorIPiS1_EET_S9_St12__false_type[_ZNSt6vectorIiSaIiEE18_M_insert_dispatchIPKiEEvN9__gnu_cxx17__normal_iteratorIPiS1_EET_S9_St12__false_type]+0x32): undefined reference to `void std::vector<int, std::allocator<int> >::_M_range_insert<int const*>(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const*, int const*, std::forward_iterator_tag)'
/tmp/cc1QxQUn.o: In function `void std::vector<int, std::allocator<int> >::_M_assign_dispatch<std::move_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > > >(std::move_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > >, std::move_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > >, std::__false_type)':
vec.cc:(.text._ZNSt6vectorIiSaIiEE18_M_assign_dispatchISt13move_iteratorIN9__gnu_cxx17__normal_iteratorIPiS1_EEEEEvT_S9_St12__false_type[_ZNSt6vectorIiSaIiEE18_M_assign_dispatchISt13move_iteratorIN9__gnu_cxx17__normal_iteratorIPiS1_EEEEEvT_S9_St12__false_type]+0x2d): undefined reference to `void std::vector<int, std::allocator<int> >::_M_assign_aux<std::move_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > > >(std::move_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > >, std::move_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > >, std::forward_iterator_tag)'
collect2: error: ld returned 1 exit status
Upvotes: 3
Views: 702
Reputation: 302757
From [temp.explicit]:
An explicit instantiation that names a class template specialization is also an explicit instantiation of the same kind (declaration or definition) of each of its members (not including members inherited from base classes and members that are templates) that has not been previously explicitly specialized in the translation unit containing the explicit instantiation, except as described below.
So while you're explicitly instantiating std::vector<int>
, you're not instantiating any of its member function templates - so you're getting undefined references for all of those (e.g. _M_emplace_back_aux
is a function template). You'd have to add all of those explicitly:
template void std::vector<int>::_M_emplace_back_aux<int>(int&& );
template void std::vector<int>::_M_emplace_back_aux<const int&>(const int& );
template void std::vector<int>::_M_assign_aux<int const*>(int const*, int const*, std::forward_iterator_tag);
...
Or just - let implicit instantiation just do its thing.
Upvotes: 3