首页 > 解决方案 > C++ 模板函数以随机顺序接受参数

问题描述

我正在编写一个 C++ 网络库,并希望主(模板)函数以随机顺序接受参数,以使其更加用户友好,就像CPR库一样。

模板函数将同时接受多达 10 个参数,每个参数都有不同的类型。有没有办法实例化模板以接受参数类型的任何随机顺序,而不是必须手动包含每种可能性的代码?

例如 - 在这种情况下,使用 3 个参数,每个参数都有不同的类型:

.h 文件

namespace foo
{
    template <typename T, typename U, typename V> void do(const T& param_a, const U& param_b , const V& param_c);
};

.cpp 文件

template <typename T, typename U, typename V>
void foo::do(const T& param_a, const U& param_b, const V& param_c) {
//do lots of stuff
}

//instantiate to allow random param order 
template void foo::do<int, std::string, long>(const int&, const std::string&, const long&);
template void foo::do<int, long, std::string>(const int&, const long&, const std::string&);
template void foo::do<int, std::string, int>(const int&, const std::string&, const int&);
//etc... to cover all possible param orders

标签: c++c++11templates

解决方案


如果您的目标是匹配给定库的 API 设计,那么最好的学习方法是深入挖掘其源代码并剖析它。

考虑这段代码(我仍然使用 CPR 作为示例,因为您提到它作为参考):

cpr::Session session;
session.SetOption(option1);
session.SetOption(option2);
session.SetOption(option3);

您需要一种可以处理option1, option2,的方法...,无论它们以何种顺序提供。随后的调用SetOption可以替换为单个SetOptions(option3, option1, option2). 因此我们需要一个可变参数 SetOptions方法:

template<typename Ts...> // important: don't specialize the possible argument types here
void SetOptions(Ts&&... ts)
{ /* do something for each param in ts... */ }

问题是“如何调用参数包SetOption中的每个项目ts?”。这是std::initializer_list. 你可以在这里找到一个简单的例子。

这里的关键是要有一个重载函数,它可以分别处理每个参数类型(例如在 CPR 中使用 SetOptions)。然后,在“permutable”函数中,为每个参数调用重载函数,一次一个(例如在 CPR 中,然后在各个 地方使用)。

不过要注意的一件事是,您可以传递相同类型的多个参数。根据您想要实现的目标,这可能是一个问题,也可能不是。

此外,您可以使用不受支持的参数类型(不匹配任何重载)调用该方法,在这种情况下,错误消息并不总是明确的,具体取决于您使用的编译器。但是,这是您可以使用static_asserts 克服的问题。


推荐阅读