我正在嘗試std::vector使用自定義型別創建顯式模板實體化。
//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 */
另外,我有一個帶有外部實體化宣告的包裝器
//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.cpp
#include "test_include.hpp"
template struct Test<std::string>;
template class std::allocator<Test<std::string>>;
template class std::vector<Test<std::string>>;
主檔案:
#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;
}
當我嘗試構建它時,我看到以下錯誤:
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
令人驚訝的是,如果Test該類具有默認建構式,則代碼編譯成功。
我應該添加或更改什么以使其作業?
編譯器版本:clang 11。
uj5u.com熱心網友回復:
根據標準,當您顯式實體化模板時,類的所有非模板化成員都會被實體化(相對于來自每個 [temp.inst] 的隱式實體化的按需實體化)。
[temp.explicit] *
命名類模板特化的顯式實體化也是其每個直接非模板成員的相同型別(宣告或定義)的顯式實體化,這些成員之前沒有在包含顯式實體化的翻譯單元中顯式特化,前提是顯式實體化的模板引數滿足該成員的關聯約束(如果有)
問題是vector像resize這樣的非模板成員需要T默認可構造。MSVC 編譯器在其錯誤訊息中更明顯地說明了這一點:
vector(1191): note: while compiling class template member function 'void std::vector<Test<std::string>,std::allocator<Test<std::string>>>::resize(const unsigned __int64)'
修復
標準語* 中的關鍵短語是
[...] 前提是顯式實體化的模板引數滿足該成員的相關約束(如果有)
問題似乎是, 的實作vector還沒有趕上 C 20;函式 likeresize不受 eg, 的約束requires DefaultConstructible<T>。查看 libstdc 的矢量源證實了這種情況。
實際的解決方案可能是“等一下”。
與此同時,如果你能為你的類提供一個默認的建構式,那就去做吧。否則,您不能使用顯式模板實體化。
* 在 C 20 之前不存在關于約束的措辭,因此如果您希望此問題最終得到修復,您還需要升級您的 C 版本
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/326460.html
下一篇:未宣告的識別符號-模板C
