Ant*_*rez 1 c++ templates aggregate-initialization type-deduction c++17
C++17 有两大特性:聚合初始化和模板类型推导(对于类)。聚合初始化允许您实例化字段而无需复制或移动它们,并且模板类型推导使您不必指定参数的类型。
\n下面代码中的类Wrapper就是一个例子。只要HAVE_MOVE_AND_COPY未定义,它就具有聚合初始化,但模板类型推导不起作用。
另一方面,如果定义HAVE_MOVE_AND_COPY 了,则模板类型推导有效,但聚合初始化会中断。我怎样才能两者兼得?
#include <cstdio>\n#include <utility>\n\ntemplate<class T> \nstruct Wrapper {\n T value;\n #ifdef HAVE_MOVE_AND_COPY\n Wrapper(T const & val) : value{val} {}\n Wrapper(T && val) : value{std::move(val)} {}\n #endif\n Wrapper(Wrapper const &) = default;\n Wrapper(Wrapper &&) = default;\n \n\n};\n\nstruct VocalClass {\n VocalClass() { puts("VocalClass()"); }\n VocalClass(VocalClass const&) { puts("VocalClass(VocalClass const &)"); }\n VocalClass(VocalClass &&) { puts("VocalClass(VocalClass &&)"); }\n};\n\nint main() {\n Wrapper<VocalClass> w { VocalClass() }; \n\n #ifdef TRY_DEDUCTION\n Wrapper w2 { VocalClass() }; \n #endif\n}\nRun Code Online (Sandbox Code Playgroud)\n$ c++ -std=c++17 example.cc && ./a.out\nVocalClass()\nRun Code Online (Sandbox Code Playgroud)\nVocalClass被移动:$ c++ -DHAVE_MOVE_AND_COPY -DTRY_DEDUCTION -std=c++17 example.cc && ./a.out \nVocalClass()\nVocalClass(VocalClass &&)\nVocalClass()\nVocalClass(VocalClass &&)\nRun Code Online (Sandbox Code Playgroud)\nHAVE_MOVE_AND_COPY,模板类型推导就会中断:sky@sunrise:~$ c++ -DTRY_DEDUCTION -std=c++17 example.cc && ./a.out \nexample.cc: In function \xe2\x80\x98int main()\xe2\x80\x99:\nexample.cc:27:31: error: class template argument deduction failed:\n Wrapper w2 { VocalClass() };\n ^\nexample.cc:27:31: error: no matching function for call to \xe2\x80\x98Wrapper(VocalClass)\xe2\x80\x99\nexample.cc:12:5: note: candidate: \xe2\x80\x98template<class T> Wrapper(Wrapper<T>&&)-> Wrapper<T>\xe2\x80\x99\n Wrapper(Wrapper &&) = default;\n ^~~~~~~\nexample.cc:12:5: note: template argument deduction/substitution failed:\nexample.cc:27:31: note: \xe2\x80\x98VocalClass\xe2\x80\x99 is not derived from \xe2\x80\x98Wrapper<T>\xe2\x80\x99\n Wrapper w2 { VocalClass() };\n ^\nexample.cc:11:5: note: candidate: \xe2\x80\x98template<class T> Wrapper(const Wrapper<T>&)-> Wrapper<T>\xe2\x80\x99\n Wrapper(Wrapper const &) = default;\n ^~~~~~~\nexample.cc:11:5: note: template argument deduction/substitution failed:\nexample.cc:27:31: note: \xe2\x80\x98VocalClass\xe2\x80\x99 is not derived from \xe2\x80\x98const Wrapper<T>\xe2\x80\x99\n Wrapper w2 { VocalClass() };\n ^\nexample.cc:5:8: note: candidate: \xe2\x80\x98template<class T> Wrapper(Wrapper<T>)-> Wrapper<T>\xe2\x80\x99\n struct Wrapper {\n ^~~~~~~\nexample.cc:5:8: note: template argument deduction/substitution failed:\nexample.cc:27:31: note: \xe2\x80\x98VocalClass\xe2\x80\x99 is not derived from \xe2\x80\x98Wrapper<T>\xe2\x80\x99\n Wrapper w2 { VocalClass() };\n \nRun Code Online (Sandbox Code Playgroud)\n有什么方法可以同时进行模板类型推导和聚合初始化吗?
\n首先,术语是“类模板参数推导”。
其次,你需要的是一个推演指南:
template<class T>
struct Wrapper {
T value;
};
template <typename T>
Wrapper(T) -> Wrapper<T>; // this is a deduction guide
Run Code Online (Sandbox Code Playgroud)
如果没有构造函数,则需要其他方法来指导推导。这就是它的用途,它允许:
Wrapper w{4}; // ok, Wrapper<int>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1198 次 |
| 最近记录: |