c++ - How to implement static virtual member function -


tl/dr: there (more convenient) way implement such functionality?

i have invoke same static code both class-type , class-instance represented reference base:

int main() {     // invokes on class     bar<c1>(); // invokes c1::foo()     bar<c2>(); // invokes c2::foo()      // invokes on instance     bar(c1()); // invokes c1::foo()     bar(c2()); // invokes c2::foo() } 

but problem can't implement without code duplication. each derived class have write both static , virtual methods. static - because can't invoke virtual method on class, , virtual, calls static - because there's no way distinguish object behaviour except virtual methods:

template<typename t> void bar() {     t::foo(); }  void bar(a const &r) {     r.foo(); } 

thus, workaround solve problem of duplicating code:

#include <iostream>  class { public:     virtual void foo() const = 0; };  template<typename derived_t> class b: public { public:     virtual void foo() const     {         derived_t::foo();     } };  class c1 : public b<c1> { public:     static void foo()     {         std::cout << "c1::foo()" << std::endl;     } };  class c2 : public b<c2> { public:     static void foo()     {         std::cout << "c2::foo()" << std::endl;     } }; 

this approach works perfectly, has @ least 2 inconveniences.

firstly, had introduce auxiliary template class b implemented virtual method.

secondly, every inheritance chain (from b final class) must consists of templates makes impossible using intermediate class pointer/reference type. eg. <- b <- t1 <- t2 <- c , t1 , t2 must template classes provide c::foo().

one possible solution crtp base class injection.

template <typename t, typename... bases>  struct crtpfooinjector : bases...  {     virtual void vfoo() { t::foo(); } };     

this injector template. implements virtual version of foo, nothing else.

struct base: crtpfooinjector<base> {     static int foo() { std::cout << "base::foo()" << std::endl; } };   struct der1 : crtpfooinjector<der1, base> {     static int foo() { std::cout << "der1::foo()" << std::endl; } };   struct der2 : crtpfooinjector<der2, base> {     static int foo() { std::cout << "der2::foo()" << std::endl; } };   struct der12 : crtpfooinjector<der12, der1, der2> {     static int foo() { std::cout << "der12::foo()" << std::endl; } }; 

now instead of normal hierarchy base <- der1 <- der12 have different 1 injector <- base <- injector <- der1 <- injector <- der12, should transparent users.

if need mix in virtual base classes:

template <typename t> struct virtual : virtual t { };  struct der1 : crtpfooinjector<der1, virtual<base>> ... 

Comments

Popular posts from this blog

qt - Using float or double for own QML classes -

Create Outlook appointment via C# .Net -

ios - Swift Array Resetting Itself -