递归变分模板函数-没有歧义



我目前正在研究可变模板,作为一个小练习来消化我读到的一些东西,我写了一个小函数来输出它所有参数类型的名称:

#include "stdafx.h"
#include <iostream>
#include <string>
template<typename Next, typename... Rest>
std::string get_arg_types(Next next, Rest... rest)
{
return std::string(typeid(Next).name()) + "n" + get_arg_types(rest...);
}
template<typename Last>
std::string get_arg_types(Last last)
{
return std::string(typeid(Last).name());
}
int main()
{
float f = 0;
double d = 0;
int i = 0;
std::cout << get_arg_types(f, d, i);
return 0;
}

令我惊讶的是,这是用VC++12.0编译的,而且(似乎(运行得很好。

当只剩下一个参数时,由于重载之间的歧义,我预计会出现错误,因为我读到模板参数包可以是空的/包含0个参数。

所以我的问题是为什么这样做?如何解决"潜在的歧义"?两个函数的签名是否都不相同,只有一个参数?我觉得我可能在某个地方错过了一些重要的概念,因为在我的脑海中,上面的例子不应该编译,但显然我错了。

问候:(

您的代码有问题,但原因不同。正如在回答相关问题时所指出的,当递归调用可变模板函数重载时,模糊调用,代码中的第二个重载被认为更专业。但是,它应该出现在带有参数包的例程之前。使用gcc8.2.1或clang6.0.1编译代码会出现类似的错误

variadic.cpp: In instantiation of ‘std::__cxx11::string get_arg_types(Next, Rest ...) [with Next = int; Rest = {}; std::__cxx11::string = std::__cxx11::basic_string<char>]’:
variadic.cpp:7:67:   recursively required from ‘std::__cxx11::string get_arg_types(Next, Rest ...) [with Next = double; Rest = {int}; std::__cxx11::string = std::__cxx11::basic_string<char>]’
variadic.cpp:7:67:   required from ‘std::__cxx11::string get_arg_types(Next, Rest ...) [with Next = float; Rest = {double, int}; std::__cxx11::string = std::__cxx11::basic_string<char>]’
variadic.cpp:23:39:   required from here
variadic.cpp:7:67: error: no matching function for call to ‘get_arg_types()’
return std::string(typeid(Next).name()) + "n" + get_arg_types(rest...);
error: no matching function for call to ‘get_arg_types()

正如您从错误中看到的那样,即使get_arg_types只有一个参数,编译器也会选择第一个重载,然后在没有参数的情况下调用get_arg_types。一个简单的解决方案是使用模板参数包将带有单个参数的get_arg_types的重载移到例程之前,或者在通用例程之前添加单个参数get_arg_types的声明。

或者,您可以取消get_arg_types的专业化单个参数,并添加一个具有0个参数的专业化:

std::string get_arg_types()
{
return std::string();
}

同样,这种专门化应该放在(或者至少声明(模板例程之前。请注意,对于第二个解决方案,输出略有变化。

最新更新