mercredi 13 octobre 2021

How to create an explicit template instantiation declaration for std::vector with custom type?

I am trying to create an explicit template instantiation for std::vector with a custom type.

//test.hpp

#ifndef TEST_HPP_JXIGJWWK
#define TEST_HPP_JXIGJWWK

template<typename T>
struct Test {
    Test(int) {}
    T value;
};

#endif /* end of include guard: TEST_HPP_JXIGJWWK */

Also, I have a wrapper with an extern instantiation declaration

//test_include.hpp

#ifndef TEST_INCLUDE_HPP_IBQ8DOTW
#define TEST_INCLUDE_HPP_IBQ8DOTW

#include <vector>
#include <string>
#include "test.hpp"

extern template struct Test<std::string>;
extern template class std::allocator<Test<std::string>>;
extern template class std::vector<Test<std::string>>;

#endif /* end of include guard: TEST_INCLUDE_HPP_IBQ8DOTW */

Another file where I have explicit template definitions:

another.cpp
#include "test_include.hpp"

template struct Test<std::string>;
template class std::allocator<Test<std::string>>;
template class std::vector<Test<std::string>>;

The main file:

#include "test_include.hpp"
#include "another.hpp"
#include <iostream>


int main() {

    std::vector<Test<std::string>> v;
    std::cout << v.size() << std::endl;

    return 0;
}

When I try to build it I see the following error:

In file included from /usr/include/c++/9/vector:65,
                 from /home/dima/extern_template_check/test_include.hpp:4,
                 from /home/dima/extern_template_check/another.cpp:1:
/usr/include/c++/9/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = Test<std::__cxx11::basic_string<char> >; _Args = {}]’:
/usr/include/c++/9/bits/stl_uninitialized.h:545:18:   required from ‘static _ForwardIterator std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Test<std::__cxx11::basic_string<char> >*; _Size = long unsigned int; bool _TrivialValueType = false]’
/usr/include/c++/9/bits/stl_uninitialized.h:601:20:   required from ‘_ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Test<std::__cxx11::basic_string<char> >*; _Size = long unsigned int]’
/usr/include/c++/9/bits/stl_uninitialized.h:663:44:   required from ‘_ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, std::allocator<_Tp>&) [with _ForwardIterator = Test<std::__cxx11::basic_string<char> >*; _Size = long unsigned int; _Tp = Test<std::__cxx11::basic_string<char> >]’
/usr/include/c++/9/bits/stl_vector.h:1603:36:   required from ‘void std::vector<_Tp, _Alloc>::_M_default_initialize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = Test<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<Test<std::__cxx11::basic_string<char> > >; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/home/dima/extern_template_check/another.cpp:5:21:   required from here
/usr/include/c++/9/bits/stl_construct.h:75:7: error: no matching function for call to ‘Test<std::__cxx11::basic_string<char> >::Test()’
   75 |     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
      |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/dima/extern_template_check/test_include.hpp:6,
                 from /home/dima/extern_template_check/another.cpp:1:
/home/dima/extern_template_check/test.hpp:6:5: note: candidate: ‘Test<T>::Test(int) [with T = std::__cxx11::basic_string<char>]’
    6 |     Test(int) {}
      |     ^~~~
/home/dima/extern_template_check/test.hpp:6:5: note:   candidate expects 1 argument, 0 provided
/home/dima/extern_template_check/test.hpp:5:8: note: candidate: ‘Test<std::__cxx11::basic_string<char> >::Test(const Test<std::__cxx11::basic_string<char> >&)’
    5 | struct Test {
      |        ^~~~
/home/dima/extern_template_check/test.hpp:5:8: note:   candidate expects 1 argument, 0 provided
/home/dima/extern_template_check/test.hpp:5:8: note: candidate: ‘Test<std::__cxx11::basic_string<char> >::Test(Test<std::__cxx11::basic_string<char> >&&)’
/home/dima/extern_template_check/test.hpp:5:8: note:   candidate expects 1 argument, 0 provided

Surprisingly if the Test class has a default ctor, the code compiles successfully.

What should I add or change to make it work?

Compiler version: clang 11.

Aucun commentaire:

Enregistrer un commentaire