为没有模板参数的可变模板递归创建基本情况
我正在尝试将递归与可变参数模板一起使用。我希望基本情况具有零模板参数。在查看了以前问题的 stackoverflow 答案后,我发现了对这个问题的两种回应:
- 你不应该专门化模板函数。赫伯·萨特 (Herb Sutter) 在这里写道:http : //www.gotw.ca/publications/mill17.htm
- 您使用
template <typename = void>或template <typename T = void>。例如,这里的第一个答案:如何编写可变参数模板递归函数?
我试图在我的问题中使用解决方案 (2),但收到错误。这是一个最小的、可重现的示例:
#include <iostream>
template<typename = void> // base case
int NumArguments() {
return 0;
}
template<typename FirstArg, typename... RemainingArgs>
int NumArguments() {
return 1 + NumArguments<RemainingArgs...>();
}
class A {
public:
A() {}
};
int main() {
std::cout << NumArguments<A>();
return 0;
}
在 Microsoft Visual C++20 中编译给出了错误:
error C2668: 'NumArguments': ambiguous call to overloaded function
message : could be 'int NumArguments<A,>(void)'
message : or 'int NumArguments<A>(void)'
message : while trying to match the argument list '()'
这个错误信息是什么意思?如何使用可变参数模板为递归创建零参数基本情况?
编辑:评论中要求更完整地描述我的问题。问题真的是问题标题,而不是“我如何让我的代码工作?”,但我还没有编译我的代码,所以我决定分享它。
NumArguments是另一个函数的替代品,ComputeSize它接受输入Args并返回一个std::size_t.
template<typename = void>
constexpr std::size_t ComputeSize() {
return 0;
}
template<typename FirstArg, typename... RemainingArgs>
constexpr std::size_t ComputeSize() {
return FuncReturnSize<FirstArg>() + ComputeSize<RemainingArgs...>();
}
Args in的可能列表Args是有限的,并且在编译之前是已知的。FuncReturnSize这些 中的每一个都超载了Args。例如,两个可能的“重载”(?)是
template <typename T>
requires ((requires (T t) { { t.Func()} -> std::same_as<double>; }) || (requires (T t) { { t.Func() } -> std::same_as<std::vector<double>>; }))
constexpr std::size_t FuncReturnSize() {
return 1;
}
template <typename T>
requires requires (T t) { { t.Func() } -> is_std_array_concept<>; }
constexpr std::size_t FuncReturnSize() {
return std::tuple_size_v<decltype(std::declval<T&>().Func())>;
}
这个概念is_std_array_concept<>应该检查返回值是否t.Func()是某个大小的数组。我还不确定它是否有效。它定义为
template<class T>
struct is_std_array : std::false_type {};
template<class T, std::size_t N>
struct is_std_array<std::array<T, N>> : std::true_type {};
template<class T>
struct is_std_array<T const> : is_std_array<T> {};
template<class T>
struct is_std_array<T volatile> : is_std_array<T> {};
template<class T>
struct is_std_array<T volatile const> : is_std_array<T> {};
template<typename T>
concept is_std_array_concept = is_std_array<T>::value;
我希望所有这些计算都在编译时完成,所以我定义了
template<std::size_t N>
std::size_t CompilerCompute() {
return N;
}
我现在应该能够ComputeSize在编译时像这样:
CompilerCompute<ComputeSize<Args...>()>()