2011-08-07 12 views
7

Jeśli moja klasa podstawowa ma funkcję func(int), a moja klasa pochodna ma funkcję func(double), pochodna func(double) ukrywa base::func(int). Mogę użyć using przynieść wersję bazową w wykazie czerpać z dnia przeciążeń:Potrzebuję czegoś takiego jak "using Base :: *;"

struct base 
{ 
    void func(int); 
}; 

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

OK, świetnie. Ale co, jeśli nie jestem pewien, czy base ma numer func(), czy też nie? tzn. ponieważ robię metaprogramowanie szablonowe, nie jestem właściwie pewien, co to jest base, ale chcę, aby jego funkcje były na tym samym poziomie - jeśli istnieją. czyli zmienić powyższy przykład do:

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 :-(

muszę using_if jak boost::enable_if. Nie wydaje się możliwe ...

Z góry dziękuję.

+1

Co chcesz robić w ostateczności? Do czego służy wyrażenie "wyprowadzono "? –

+0

Buduję klasy, które opcjonalnie wdrażają niektóre funkcje, w zależności od tego, jak/gdzie są używane. Co jest w zasadzie tylko refaktoryzacją, do pewnego stopnia - tj. Zamiast pisania klasy XWithFeatureA, XWithFeatureB, XWithFeatureAandB, ... która zamienia się w wiele klas tytułów, chcę mieć X , gdzie feature_traits decyduje, które funkcje są używane. – tony

+0

Funkcje takie jak "pozwala słuchaczom", "ma ustawiacze niestandardowe" itp. Dla obiektów w systemie. Nie sądzę, żebym mógł (lub wolno mi to opisać) opisać go na tyle, aby był przekonany, że system z opcjonalnymi funkcjami ma sens. – tony

Odpowiedz

0

Chyba muszę zrobić coś jak

struct dummy_func 
{ 
private: 
    struct dumb_type {}; 

// interesting: does this need to be public? 
public: 
    // use a type that no one can see, so func is never chosen by ADT 
    // and vararg just for paranoia 
    void func(dumb_type, dumb_type, dumb_type,...) { }; 
}; 

... 
template <typename T> 
struct has_func 
{ 
    enum { value = /* insert metaprogramming magic that checks for T::func */ } 
}; 

template <typename Base> 
struct derived : Base 
{ 
    using enable_if<has_func<Base>, Base, dummy_func>::type::func; 
    ... 
}; 

Grrr. Oczywiście to nie działa, ponieważ dummy_func nie jest bazą derived. W moim przypadku mógłbym w razie potrzeby go wyprowadzić. Ale wciąż ledwo satysfakcjonujący.

+0

Domyślam się, że to nie to samo, co "używanie Base :: *", ale "* -" używa wszystkiego z tej klasy ", jeśli to możliwe, dałoby mi również to, co ja chciał. – tony

1

Skoro jesteś gotów do wprowadzenia using sprawozdania do swojej klasie pochodnej, zakładam, że wiesz beforehands której członkowie mogą Państwo byłby zainteresowany przynieść Można to zrobić za pomocą 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; } 
}; 

Niestety dla wszystkich instrukcji drukowania. Teraz jeśli spróbujesz

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

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

powinieneś zobaczyć

konstruktor: pochodzący z
ctor: pochodzący bez
func (int)
func (podwójne)
func (podwójne)
func (podwójne)

Obv Iously, to będzie monstrualna, jeśli spróbujesz przetestować kilka funkcji. Gdybym robił takie programy w stylu mixin, wolałbym raczej używać funkcji o różnych nazwach dla różnych funkcji, aby się nie ukrywać - wtedy publiczne dziedzictwo byłoby wszystkim, co jest potrzebne. Interesujące pytanie w każdym przypadku.

Powiązane problemy