gpt4 book ai didi

c++ - 可变参数模板调度器

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:52:42 25 4
gpt4 key购买 nike

我想使用可变参数模板来帮助解决使用 va-args 的问题。基本上,我想调用一个单一的函数,将一个“命令”连同一个可变参数列表传递给该函数,然后将这些参数分派(dispatch)给另一个函数。

我已经使用经过验证的(但不是类型安全的)va_list 实现了这个。这是我使用可变参数模板所做的尝试。下面的示例无法编译,因为您很快就会发现原因...

#include <iostream>

using namespace std;
typedef enum cmd_t
{
CMD_ZERO,
CMD_ONE,
CMD_TWO,
} COMMANDS;


int cmd0(double a, double b, double c)
{
cout << "cmd0 " << a << ", " << b << ", " << c << endl;
return 0;
}

int cmd1(int a, int b, int c)
{
cout << "cmd1 " << a << ", " << b << ", " << c << endl;
return 1;
}

template<typename... Args>
int DispatchCommand(COMMANDS cmd, Args... args)
{
int stat = 0;
switch (cmd)
{
case CMD_ZERO:
cmd0(args...);
break;
case CMD_ONE:
cmd1(args...);
break;
default:
stat = -1;
break;
}
return stat;
}

int main()
{
int stat;
stat = DispatchCommand(CMD_ZERO, 1, 3.141, 4);
stat = DispatchCommand(CMD_ONE, 5, 6, 7);
stat = DispatchCommand(CMD_TWO, 5, 6, 7, 8, 9);

system("pause");
return 0;
}

有人知道如何修改此函数以正确使用可变参数模板吗?

最佳答案

编写一些代码,给定一个函数指针和一组参数,使用这些有效参数中最长的前缀调用它。

template<class...>struct types{using type=types;};
template<class types0, size_t N, class types1=types<>>
struct split;

template<class t00, class...t0s, size_t N, class...t1s>
struct split<types<t00,t0s...>,N,types<t1s...>>:
split<types<t0s...>,N-1,types<t1s...,t00>>
{};
template<class...t0s, class...t1s>
struct split<types<t0s...>,0,types<t1s...>>
{
using right=types<t0s...>;
using left=types<t1s...>;
};
template<class>using void_t=void;
template<class Sig,class=void>
struct valid_call:std::false_type{};
template<class F, class...Args>
struct valid_call<F(Args...), void_t<
decltype( std::declval<F>()(std::declval<Args>()...) )
>>:std::true_type {};

template<class R, class types>
struct prefix_call;

template<class R, class...Args>
struct prefix_call<R, types<Args...>> {
template<class F, class... Extra>
std::enable_if_t< valid_call<F(Args...)>::value, R >
operator()(R default, F f, Args&&...args, Extra&&...) const
{
return std::forward<F>(f)(args...);
}
template<class F, class... Extra>
std::enable_if_t< !valid_call<F(Args...)>::value, R >
operator()(R default, F f, Args&&...args, Extra&&...) const
{
return prefix_call<R, typename split<types<Args...>, sizeof...(Args)-1>::left>{}(
std::forward<R>(default), std::forward<F>(f), std::forward<Args>(args)...
);
}
};

template<class R>
struct prefix_call<R, types<>> {
template<class F, class... Extra>
std::enable_if_t< valid_call<F()>::value, R >
operator()(R default, F f, Extra&&...) const
{
return std::forward<F>(f)();
}
template<class F, class... Extra>
std::enable_if_t< !valid_call<F()>::value, R >
operator()(R default, F f, Extra&&...) const
{
return std::forward<R>(default);
}
};

以上代码可能有错别字。

template<typename... Args>
int DispatchCommand(COMMANDS cmd, Args... args)
{
int stat = 0;
switch (cmd) {
case CMD_ZERO: {
stat = prefix_call<int, Args...>{}(-1, cmd0, std::forward<Args>(args)...);
} break;
case CMD_ONE: {
stat = prefix_call<int, Args...>{}(-1, cmd1, std::forward<Args>(args)...);
} break;
default: {
stat = -1;
} break;
}
return stat;
}

如果 cmd0cmd1 被覆盖,您将不得不使用重载集技术。

关于c++ - 可变参数模板调度器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25773226/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com