将 Variadic 模板函数转换为许多具体函数
Convert Variadic Template Function to many concrete functions
是否有编译器标志或技术强制为每次调用具有唯一签名的可变函数模板生成一个非可变函数?
在以下示例中,编译器创建带有签名 int (int, float, double)
、int (float, double)
和 int (double)
.
的可变参数模板
#include <iostream>
using namespace std;
template<class IntT, class argsf>
IntT SumArgs(const argsf& firstArg)
{
return static_cast<IntT>(firstArg);
}
template<class IntT, class argsf, class ...argst>
IntT SumArgs(const argsf& firstArg, const argst&... restArgs)
{
return static_cast<IntT>(firstArg + SumArgs<IntT>(restArgs...));
}
int main()
{
cout<<"Sum result: " << SumArgs<int>(1, 2.f, 3.5);
return 0;
}
前两个仍然是可变的。但是,在某些情况下,可能需要避免可变参数函数的开销,而是为上面列出的每个签名创建一个唯一的函数定义。有没有办法让编译器这样做?另一种方法是编写函数的版本,明确使用 0、1、2 ... n 参数来表示一些相当大的 n 并手动复制代码,但理想情况下,编译器可以为我们完成这项繁重的工作。
C++17 引入了折叠表达式,它们(希望)正是您正在寻找的:
template <class R, class... Args>
constexpr R SumArgs(const Args&... args)
{
return static_cast<R>((args + ...)); // fold expression
}
如果您不想使用可变参数模板,您可以使用 initializer_list
:
template <class R, class T>
constexpr R SumArgs(std::initializer_list<T> args)
{
return std::accumulate(args.begin(), args.end(), R{});
}
是否有编译器标志或技术强制为每次调用具有唯一签名的可变函数模板生成一个非可变函数?
在以下示例中,编译器创建带有签名 int (int, float, double)
、int (float, double)
和 int (double)
.
#include <iostream>
using namespace std;
template<class IntT, class argsf>
IntT SumArgs(const argsf& firstArg)
{
return static_cast<IntT>(firstArg);
}
template<class IntT, class argsf, class ...argst>
IntT SumArgs(const argsf& firstArg, const argst&... restArgs)
{
return static_cast<IntT>(firstArg + SumArgs<IntT>(restArgs...));
}
int main()
{
cout<<"Sum result: " << SumArgs<int>(1, 2.f, 3.5);
return 0;
}
前两个仍然是可变的。但是,在某些情况下,可能需要避免可变参数函数的开销,而是为上面列出的每个签名创建一个唯一的函数定义。有没有办法让编译器这样做?另一种方法是编写函数的版本,明确使用 0、1、2 ... n 参数来表示一些相当大的 n 并手动复制代码,但理想情况下,编译器可以为我们完成这项繁重的工作。
C++17 引入了折叠表达式,它们(希望)正是您正在寻找的:
template <class R, class... Args>
constexpr R SumArgs(const Args&... args)
{
return static_cast<R>((args + ...)); // fold expression
}
如果您不想使用可变参数模板,您可以使用 initializer_list
:
template <class R, class T>
constexpr R SumArgs(std::initializer_list<T> args)
{
return std::accumulate(args.begin(), args.end(), R{});
}