I recently had a thought of implementing virtual functions without virtual tables or storing a pointer with CRTP (though using static_cast<CRTP&>(*this) instead.
The initial set up is rather cumbersome compared to conventional virtual functions.
So the code is:
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;
}
However there is a problem: virtual_set_up<dummy> resolves to the specialization of T with declared T::set_up causing a SEGFAULT upon execution. It happens because dummy is publicly inheriting from base, which does have a set_up method.
Given that the previous problem is solvable, does this add any efficiency over having a conventional virtual function?