gpt4 book ai didi

templates - C++/C++11 - 可变参数模板的 Switch 语句?

转载 作者:行者123 更新时间:2023-12-02 22:02:13 25 4
gpt4 key购买 nike

假设我有一些这样的结构:

struct MyStruct1 {

inline void DoSomething() {
cout << "I'm number one!" << endl;
}

};

struct MyStruct2 {

static int DoSomething() {

cout << "I'm the runner up." << endl;
return 1;

}

};

struct MyStruct3 {

void (*DoSomething)();

MyStruct3() {
DoSomething = &InternalFunction;
}

static void InternalFunction() {
cout << "I'm the tricky loser." << endl;
}

};

正如您所看到的,对于所有三个结构,我可以在该结构的对象上调用 DoSomething() 并让它工作(尽管每个结构的实现方式不同):

MyStruct1 a;
MyStruct2 b;
MyStruct3 c;

a.DoSomething(); // works, calls Struct1's instance function
b.DoSomething(); // works, calls Struct2's static function, discards return value
c.DoSomething(); // works, calls Struct3's function pointer

现在,假设我将这些结构的任意选择放入一个元组中:

tuple<MyStruct2, MyStruct3, MyStruct2, MyStruct1> collection;

假设我想获取其中一个元素并根据运行时确定的索引运行其 DoSomething() 函数。为了实现这一点,我可以使用 switch 语句:

switch(index) {

case 0: get<0>(collection).DoSomething(); break;
case 1: get<1>(collection).DoSomething(); break;
case 2: get<2>(collection).DoSomething(); break;
case 3: get<3>(collection).DoSomething(); break;

}

这工作得很好,但当需要使用多个不同排列(并且可能比 4 元素长得多)的元组来完成时,它会变得非常乏味、重复且容易出错。如果能够根据可变参数模板中的元素数量自动生成 switch 语句,那将会非常方便。伪代码:

template <typename... T>
void DoSomethingByIndex(int index, tuple<T...>& collection) {

switch(index) {

STATIC_REPEAT(sizeof...(T), X) {
case X: get<X>(collection).DoSomething(); break;
}

}

}

C++11 中是否有任何机制可以让我实现这一目标?如果没有,我知道我无疑可以将解决方案与模板中的函数指针列表组合在一起,但我只是好奇是否存在这样的东西,因为它更适合我的目的。我确信 switch 语句的编译器生成的跳转列表也比我自制的函数指针解决方案更有效。

最佳答案

您可以使用数组来桥接编译时和运行时:(ab)使用可变参数模板静态初始化数组元素,然后使用运行时参数索引到数组中。棘手的部分是为数组找到正确的元素类型。此外,由于我们需要模板在元组索引上而不是在元组元素上是可变参数,因此我将使用我通常的技巧。

template<int... Indices>
struct indices {
typedef indices<Indices..., sizeof...(Indices)> next;
};

template<int N>
struct build_indices {
typedef typename build_indices<N - 1>::type::next type;
};

template<>
struct build_indices<0> {
typedef indices<> type;
};

// No need to be variadic on the tuple elements as we don't care about them
// So I'm using perfect forwarding for the tuple
template<typename Tuple, int... Indices>
void
do_something_by_index(Tuple&& tuple, int index, indices<Indices...>)
{
using std::get;

typedef void (*element_type)(Tuple&&);
static constexpr element_type table[] = {
[](Tuple&& tuple)
{ get<Indices>(std::forward<Tuple>(tuple)).DoSomething(); }
...
};

table[index](std::forward<Tuple>(tuple));
}

// Proverbial layer of indirection to get the indices
template<typename Tuple>
void
do_something_by_index(Tuple&& tuple, int index)
{
typedef typename std::decay<Tuple>::type decay_type;
constexpr auto tuple_size = std::tuple_size<decay_type>::value;
typedef typename build_indices<tuple_size>::type indices_type;

do_something_by_index(std::forward<Tuple>(tuple), index, indices_type{});
}

关于templates - C++/C++11 - 可变参数模板的 Switch 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7381805/

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