gpt4 book ai didi

c++ - 将 Switch 转换为非虚多态

转载 作者:行者123 更新时间:2023-11-30 03:01:58 26 4
gpt4 key购买 nike

我目前有一个 C++ 接口(interface)

void foo() ...

还有很多实现

void A::foo();
void B::foo();

目前foo定义如下

struct Wrapper
{
void foo()
{
if(state == STATE_A) a.foo();
else if(state == STATE_B) b.foo();
}
union {
A a;
B b;
};
State state;
}
//....
Wrapper a(STATE_A, existingA);
Wrapper b(STATE_B, existingB);
a.foo(); b.foo();

有没有更简洁的方法来做到这一点?我有多个类似 foo() 的函数和多个类似 A/B 的类。编写所有案例变得乏味/容易出错。

请注意,我不能使用虚函数(这在 N^5 循环中运行...每秒执行 1000 万次以上)。我希望编译器很难将其内联。

我曾想过将 A、B 等收集在一起并以面向数据的方式计算它们,但不幸的是我不能这样做(由于算法问题)

最佳答案

I want the compiler to inline this, hard.

这不会发生。

您正在使用运行时多态性。根据定义,编译器无法知道调用时将调用哪个函数。您将为虚拟调度付费,无论您是手动执行还是让编译器执行。

您将获得的绝对最多 内联是在对成员函数的调用中。它仍然必须根据内存访问(获取“类型”)执行条件分支才能到达“内联”部分。您添加的每个新“状态”都会向该分支添加另一个条件。充其量,这将成为一个状态表……这与虚函数指针没有什么不同:它从内存地址获取,并使用它来分支到特定代码段。

就像一个 vtable 指针,只是你浪费了时间来实现编译器可以为你做的事情。

我强烈建议您分析这一点,而不是简单地假设您的手写方法可以击败编译器。


如果您决定放弃语言级多态性,那么您应该使用 boost.variant 而适当的访问者。您的代码将如下所示:

typedef boost::variant<A, B> Wrapper;

struct FooVisitor : public boost::static_visitor<>
{
template <typename T> void operator()(T &t) {t.foo()};
};

你必须制作一个 FooVisitor对于您要调用的每个函数。要调用它,您可以这样做:

Wrapper a = existingA;
boost::apply_visitor(FooVisitor(), a);

显然,您可以将其包装在一个简单的函数中:

void CallFoo(Wrapper &a) {boost::apply_visitor(FooVisitor(), a);}

事实上,您可以制作一个完整的模板系列:

template<typename Visitor>
void Call(Wrapper &a) {boost::apply_visitor(Visitor(), a);}

请注意,参数传递是不允许的(您必须将参数存储在访问者本身中),但它们可以有返回值(您必须将返回类型放在访问者的 boost::static_visitor<Typename_Here> 声明中)。

另请注意 boost::variant对象具有值语义,因此拷贝将复制内部对象。您还可以使用 boost::get()获取实际类型的语法,但除非您确实需要它,否则我不建议这样做。只使用访问者。

关于c++ - 将 Switch 转换为非虚多态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10544393/

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