Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I need something like "using Base::*;"

If my base class has a function func(int) and my derived class has a function func(double), the derived func(double) hides base::func(int). I can use using to bring the base version into the derive's list of overloads:

struct base
{
   void func(int);
};

struct derived : base
{
   using base::func;
   void func(double);
}

OK, great. But what if I'm not sure whether base has a func() or not? ie because I am doing template metaprogramming, I'm not actually sure what base is, but I want to bring its functions up to the same level - if they exist. ie change the above example to:

struct base_with
{
   void func(int);
};
struct base_without
{
};

template <typename Base>
struct derived : Base
{
   using Base::func;  // if Base has a func(), I want to bring it in

   void func(double);
}

derived<base_with> testwith; // compiles
derived<base_without> testwithout;  // fails :-(

I need using_if like boost::enable_if. Doesn't seem possible...

Thanks in advance.

like image 963
Tony Avatar asked Aug 07 '11 07:08

Tony


1 Answers

Since you're willing to put using statements into your derived class, I assume you know beforehands which members you may be interested to bring in. You can do this using boost::enable_if:

struct base_with
{
    void func(int) { cout << "func(int)" << endl; }
};

struct base_without { };

// Custom traits, by default assume func() isn't present
template <class T> struct has_func : public boost::false_type { };

template<> struct has_func<base_with> : public boost::true_type { };

// Again, if nothing else is known, assume absence of func(int)
template <typename Base, class UseFunc = void> struct derived : Base
{
    derived() { cout << "ctor: derived without" << endl; }
    void func(double) { cout << "func(double)" << endl; }
};

// Derived with func(int)
template <typename Base> struct derived<Base, typename boost::enable_if< has_func<Base> >::type> : Base
{
    using Base::func; 
    derived() { cout << "ctor: derived with" << endl; }
    void func(double) { cout << "func(double)" << endl; }
};

Sorry for all the printing statements. Now if you try

derived<base_with> testwith; 
derived<base_without> testwithout;

testwith.func(10);
testwith.func(10.5);
testwithout.func(10);
testwithout.func(10.5);

you should see

ctor: derived with
ctor: derived without
func(int)
func(double)
func(double)
func(double)

Obviously, this is going to get monstrous if you try to test for several features. If I was doing such mixin-style programming, I'd probably rather use functions with different names for different features so they wouldn't hide each other - then public inheritance would be all that is needed. Interesting question in any case.

like image 75
Martin Gunia Avatar answered Nov 02 '22 16:11

Martin Gunia