可变参数模板未在 MSVC 中编译?
Variadic templates not compiling in MSVC?
正在尝试编译以下代码片段: 此代码显然使用了 C++11 功能,并在 C++ 编程语言书籍 §3.4.4 中进行了描述
template<typename T>
void g(T x)
{
std::cout << x << " ";
}
template<typename T, typename... Tail>
void f(T head, Tail... tail) {
g(head); // do something to head
f(tail...); // tr y again with tail
}
void f() {}
int main()
{
f(1, "Lol", 5);
getchar();
}
VS17 输出 :
C2672 'f':未找到匹配的重载函数 行:21
'void f(T,Tail...(':期望 2 个参数 - 0 提供 行:19
有什么想法吗?
这里有三件事不正确。
tail
参数阴影模板名称tail
- 没有可行的函数来处理递归调用的基本情况
f()
f()
必须在其他f(...)
之前定义,因为高级函数查找不会在此类递归函数中进行。
解决 方案
将参数tail
的名称更改为其他类似
template<typename T, typename... tail>
void f(T head, tail... ftail) { //tail here was shadowing actual template name tail so changed to ftail
g(head); // do something to head
f(ftail...); // try again with tail
}
当您对f()
进行递归调用时,有时会没有向f(..)
传递任何值,因为每次递归调用都会将传递的参数数减少 1。
假设你从f(1, "Lol", 2)
开始,在内部进行递归调用是为了f("Lol", 2)
这个轮次调用f(2)
调用f()
,但你的函数f
至少需要 1 个参数。因此错误
要解决这个问题,只需重载基本情况的f
,没有像这样的参数
void f(){
//last recursive call made
}
这是完整的代码
#include<iostream>
template<typename T>
void g(T x)
{
std::cout << x << " ";
}
void f(){ }
template<typename T, typename... tail>
void f(T head, tail... ftail) {
g(head); // do something to head
f(ftail...); // try again with tail
}
int main()
{
f(1, "Lol", 5);
getchar();
}
首先是MCVE:
template<typename T, typename... Tail>
void f(T head, Tail... tail) {
f(tail...); // tr y again with tail
}
f(1, 2, 3);
现在实例化:
f<int, int, int>(1, 2, 3);
编译为:
template<T = int, Tail...={int,int}>
void f(int head, int tail0, int tail1) {
f(tail0, tail1); // tr y again with tail
}
递归调用是:
f<int,int>(tail0, tail1); // tr y again with tail
编译为:
template<T = int, Tail...={int}>
void f(int head, int tail0) {
f(tail0); // tr y again with tail
}
递归调用解析为:
f<int>(tail0); // tr y again with tail
编译为:
template<T = int, Tail...={}>
void f(int head) {
f(); // tr y again with tail
}
在这里,我们尝试称f()
.
没有有效的调用f()
可见,因此会出现错误。
调用f()
下的void f() {}
在这里没有帮助,因为在模板中,查找是在f()
可见之前完成的。
如果要以简单的方式解决此问题,可以在f
模板上方添加inline void f(){}
。
更复杂的方法?
template<class...Ts>
void f(Ts...ts) {
using discard=int[];
(void)discard{ 0, ( void(
g(ts)
),0)...};
}
这也消除了递归。 或者在 c++17 中:
template<class...Ts>
void f(Ts...ts) {
( (void)(g(ts)), ... );
}
这也更快编译,因为它创建的符号更少(更短(。
相关文章:
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 为什么 gcc 编译这个而 msvc 没有
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- MSVC 无法编译 SFINAE 检查
- 可变参数模板未在 MSVC 中编译?
- MSVC 2010 编译应用程序和 MSVC 2019 编译应用程序之间的行为差异
- 如何使用CLion和MSVC编译器工具链编译wxWidgets Hello World应用程序而没有错误?
- 使用 msvc 15 在 Qt5.13 中编译 CUDA 代码
- std::value templated 方法的函数使用 clang 和 g++ 进行编译,但不使用 msvc 进行编译
- 使用MSVC编译的Qt程序在app.exec()上崩溃
- 使用 MSVC 编译时,msdpb* 文件的正确用法是什么?
- constexpr 函数中的 for 循环无法使用 MSVC 19.23 进行编译
- variadic模板代码中的GCC VS MSVC编译误差
- 为什么"int & const" MSVC 编译得很好?
- 为什么使用 MSVC 编译这个不正确的 std::函数初始化?
- mingw 编译错误:从 'FARPROC ' 到 'void*' 的转换无效,但 msvc 编译正常
- Boost Spirit代码,可与msvc编译,但与gcc编译错误
- 为什么下面的代码使用 MSVC++ 编译
- 在MinGW编译的项目中使用MSVC编译的Boost二进制文件
- 我怎么能摆脱*.exe.从MSVC编译的exe文件中获取manifest文件