gpt4 book ai didi

c++ - 用模板实现虚函数的覆盖机制

转载 作者:行者123 更新时间:2023-12-02 16:08:46 24 4
gpt4 key购买 nike

我最近想到了在没有虚拟表的情况下实现虚拟函数或使用 CRTP 存储指针(尽管使用 static_cast<CRTP&>(*this) 代替。

与传统的虚函数相比,初始设置相当麻烦。

所以代码是:

namespace detail
{
template<typename T, typename = void>
struct virtual_set_up
{
void operator()(T &) {}
};

template<typename T>
struct virtual_set_up<T, std::void_t<decltype(std::declval<T>().set_up())>>
{
void operator()(T &t) { t.set_up(); }
};
}

template<typename CRTP>
class base
{
public:
base() {}

void set_up() { detail::virtual_set_up<CRTP>()(static_cast<CRTP &>(*this)); }

protected:
~base() = default;
};

class settable : public base<settable>
{
public:
void set_up() { std::cout << "settable: set_up overridden" << std::endl; }
};

class dummy : public base<dummy>
{
public:
};

int main(int, char **)
{
settable s;
dummy d;

base<settable>& baseS = s;
base<dummy>& baseD = d;
baseS.set_up();
baseD.set_up();

return 0;
}

但是有一个问题:virtual_set_up<dummy>致力于 T 的特化声明 T::set_up在执行时导致 SEGFAULT。发生这种情况是因为 dummy 公开继承自 base,它确实有一个 set_up方法。

鉴于前面的问题是可以解决的,这是否比使用传统的虚函数提高了效率?

最佳答案

为了解决你的无限递归,你仍然可以比较"&dummy::setup != &base<dummy>::setup ":

namespace detail
{
template <typename B, typename T, typename = void>
struct virtual_set_up
{
void operator()(T&) {}
};

template <typename B, typename T>
struct virtual_set_up<B, T,
std::enable_if_t<!std::is_same_v<decltype(&B::set_up),
decltype(&T::set_up)>>>
{
void operator()(T& t) { t.set_up(); }
};
}

template <typename CRTP>
class base
{
public:
base() {}

void set_up() { detail::virtual_set_up<base, CRTP>()(static_cast<CRTP &>(*this)); }

protected:
~base() = default;
};

Demo

但更简单的方法是重命名/拆分 base<CRTP> 中的那个

template <typename CRTP>
class base
{
public:
base() {}

void set_up() { static_cast<CRTP &>(*this).set_up_v(); }

void set_up_v() { std::cout << "base\n"; }

protected:
~base() = default;
};

class settable : public base<settable>
{
public:
void set_up_v() { std::cout << "settable: set_up overridden" << std::endl; }
};

Demo

Does this add any efficiency over having a conventional virtual function?

所有代码都在编译时解析,没有动态调度,所以没有虚拟调度的开销...

但是这里没有任何东西是多态的:base<dummy>base<settable>是不相关的类(你不能将 std::vector<base> 存储在一起)。所以比较是不公平的。

对于在编译时已知所有类型的情况,编译器可能会使用去虚拟化优化并消除虚拟调用的开销。

关于c++ - 用模板实现虚函数的覆盖机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68618055/

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