我正在看这里发现的这个问题包含类型的类型的模板函数重载 https://stackoverflow.com/questions/44511121/template-function-overload-for-type-containing-a-type#44511121
OP在哪里用户2079802 https://stackoverflow.com/users/2079802/user2079802为他/她的问题提供了以下代码:
我正在尝试执行以下操作:
#include <iostream>
#include <vector>
#include <tuple>
template <typename T>
void f(T t) {
std::cout << "1" << std::endl;
}
template <typename T, typename V>
void f(T<std::tuple<V>> t) {
std::cout << "2" << std::endl;
}
int main() {
f(std::list<double>{}); // should use first template
f(std::vector<std::tuple<int>>{}); // should use second template
}
在 C++14 中执行此操作的最简单方法是什么?我认为我可以通过这种方式进行模式匹配,但编译器不会有它。
And 松源窑 https://stackoverflow.com/users/3309790/songyuanyao提供了这个答案:
模板参数T
用作模板名称,因此应将其声明为模板 模板参数 http://en.cppreference.com/w/cpp/language/template_parameters#Template_template_parameter. e.g.
template <template <typename...> class T, typename V>
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void f(T<std::tuple<V>> t) {
std::cout << "2" << std::endl;
}
LIVE http://rextester.com/JXC67262
提供的答案实际上修复了编译错误,并且代码确实运行正确。为了清楚起见,我正在询问有关此代码片段的问题。 OP 最初尝试对模板类型进行模式匹配,但模板参数的语法不正确。当我通过在 64 位 Intel Windows 7 机器上运行的 IDE、编译器和调试器 {MSVS 2017 CE} 运行答案时,我碰巧注意到在 OP 的函数调用中调用了其主函数:
f(std::list<double>{});
f(std::vector<std::tuple<int>>{});
第二个函数调用实际上是调用第一个函数模板而不是第二个函数模板。这确实提出了几个问题:
- 这是由于编译器优化而发生的吗?
- 这是重载解析的结果吗?
- 当编译器的引擎盖下实际发生了什么
选择使用第一个函数模板而不是第二个?
- 或者这是 MSVC 编译器的错误?
这实际上并不是 MSVC 编译器中的错误。这实际上是由于标准中有关默认模板参数的含糊不清造成的。
你看,std::vector
实际上有 2 个模板参数:类型和分配器。
如果您重构该问题的答案以考虑分配器
template <typename T>
void f(T t) {
std::cout << "1" << std::endl;
}
template <template <typename...> class T, typename V>
void f(T<std::tuple<V>, std::allocator<std::tuple<V>>> t) {
std::cout << "2" << std::endl;
}
它将在所有编译器中正常工作:msvc演示 http://rextester.com/WSQ21257, gcc demo http://rextester.com/JLENHV74448, 铿锵演示 http://rextester.com/JNGR64280.
这是原始的缺陷报告 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#150(CWG 150)
P0522R0 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0522r0.html截至2016年11月有最新的讨论,他们提出,根据标准,与您在songyuanyao的答案中引用的那种部分模板匹配将是正确的。
P0522R0 中提出的更改正在被纳入 C++17 标准(N4296 草案是我检查的标准)。在标准最终确定并且 MSVC 声称拥有完整的 C++17 支持之前,我不会将其称为编译器中的错误。目前,他们承认截至 VS 2017.3 [P2],该具体提案尚未合并到他们的编译器中(source https://blogs.msdn.microsoft.com/vcblog/2017/05/10/c17-features-in-vs-2017-3/)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)