我想要一个通用的功能'请求'它可以接受任意数量参数的元组。我想要'请求'函数将调用分配给许多其他函数,具体取决于参数的数量(当然函数的接口必须匹配)。
我编写了这段代码,但只有当我在“请求”中调用一种类型的函数时它才有效。一旦我取消对调度机制的注释(否则 - >> dispatch到fun5),一切都停止编译。
问题在于,为调度带有两个参数的函数而创建的函数体'必须编译,然后在其中有一个带有5个参数的函数,其中无法应用2个参数的元组。反之亦然。模板的经典问题。我知道我可以以某种方式将SFINAE概念应用于这个问题,但我不知道如何(我在MPL编程中不那么强大)。
#include <iostream>
#include <experimental/tuple>
enum class type { v2, v5 };
void fun2(int i1, int i2)
{
std::cout << "fun2 called, i1 = " << i1 << ", i2 = " << i2 << std::endl;
}
void fun5(bool b1, float f1, int i, char c, bool b2)
{
std::cout << "fun5 called with: " << std::boolalpha << b1 << ", " << f1 << ", " << i << ", " << c << ", " << b2 << std::endl;
}
template <typename F, typename... T>
void dispatch(F f, T... args)
{
std::experimental::apply(f, args...);
}
template <typename... T>
void request(type t, T... args)
{
if (t == type::v2)
dispatch(fun2, args...);
// else
// dispatch(fun5, args...);
}
int main()
{
auto v2 = std::make_tuple(1,1);
request(type::v2, v2);
// auto v5 = std::make_tuple(true, 1.5f, 3, 'c', false);
// request(type::v5, v5);
}
我该如何使这项工作?我需要什么样的调度机制来完成这项工作?
答案 0 :(得分:1)
我建议您使用标记和标记结构,而不是使用枚举来选择要执行的操作。然后,您只需使用简单的函数重载选择正确的dispatch
函数。
也许像
namespace type
{
struct v2_tag {};
struct v5_tag {};
v2_tag v2;
v5_tag v5;
}
template<typename... T>
void request(type::v2_tag, T... args)
{
dispatch(fun2, args...);
}
template<typename... T>
void request(type::v5_tag, T... args)
{
dispatch(fun5, args...);
}
其余代码保持不变。
答案 1 :(得分:0)
标记调度的替代方法(我强烈建议as per @Some programmer dude)将创建您自己的函数对象,该对象接受type
作为非类型模板参数,以便我们可以利用{ {3}}:
template<type t>
struct request
{
template<class... T>
void operator()(T... args) const
{
if constexpr(t == type::v2)
dispatch(fun2, args...);
else
dispatch(fun5, args...);
}
};
缺点是你必须构建一个来打电话:
auto v2 = std::make_tuple(1, 1);
request<type::v2>()(v2);
auto v5 = std::make_tuple(true, 1.5f, 3, 'c', false);
request<type::v5>()(v5);
此方法的一个变体是在static
类中使用apply
request
函数,如下所示:
template<type t>
struct request{
template<class... T>
static void apply(T... args){/*..*/}
}
然后对它的调用将会是这样的(没有时髦的空括号):
request<type::v2>::apply(v2);