mardi 1 mars 2016

How to call conditionally B::f only if derived from B in C++11?

In case when static polymorphism is used, especially in templates (e.g. with policy/strategy pattern), it may be required to call base function member, but you don't know was instantiated class actually derived from this base or not.

This easily can be solved with old good C++ ellipsis overload trick:

#include <iostream>

template <class I>
struct if_derived_from
{
    template <void (I::*f)()>
    static void call(I& x) {  (x.*f)(); }

    static void call(...) { }
};

struct A    { void reset() { std::cout << "reset A" << std::endl; } };
struct B    { void reset() { std::cout << "reset B" << std::endl; } };
struct C    { void reset() { std::cout << "reset C" << std::endl; } };
struct E: C { void reset() { std::cout << "reset E" << std::endl; } };
struct D: E {};

struct X: A, D {};

int main()
{
    X x;
    if_derived_from<A>::call<&A::reset>(x);
    if_derived_from<B>::call<&B::reset>(x);
    if_derived_from<C>::call<&C::reset>(x);
    if_derived_from<E>::call<&E::reset>(x);
    return 0;
}

The question is:

  • Is there any better simple way (e.g. SFINAE doesn't look so) to achieve same result in C++11/C++14?
  • Would empty call of ellipsis parameter function be elided by optimizing compiler? Hope such case is not special against any "normal" function.

Aucun commentaire:

Enregistrer un commentaire