13

La classe derivata nasconde il nome di un sovraccarico impostato dalla classe di base se la classe derivata ha definito lo stesso nome, ma possiamo sempre introdurre tale sovraccarico arretrato con l'utilizzo di dichiarazione:C++ - Come introdurre il set di sovraccarico dal numero variabile di basi.

template <class BASE> 
class A : public BASE 
{ 
public: 
    using BASE::some_method; 
    void some_method(); 
} 

Ma cosa succede se Presento tutti i set di sovraccarico dalle classi di base variadic? Sarei in grado di scrivere qualcosa del genere?

template <class... BASES> 
class A : public BASES... 
{ 
public: 
    using BASES::some_method...; 
    void some_method(); 
} 

ho pensato di utilizzare una classe di supporto come:

template <class... BASES> 
struct helper; 

template <> 
struct helper<> {}; 

template <class OnlyBase> 
struct helper<OnlyBase> : OnlyBase 
{ 
    using OnlyBase::some_method; 
}; 

template <class Base1, class... OtherBases> 
struct helper<Base1, OtherBases> : public Base1, public helper<OtherBases...> 
{ 
    using Base1::some_method; 
    using helper<OtherBases...>::some_method; 
}; 

e lo fa di lavoro. Ma richiede un sacco di digitazione (ovviamente posso usare la macro ma cerco di usare la funzione di compilazione di C++ ogni volta che è possibile), e quando voglio introdurre più metodi, devo cambiare molto in quel pezzo di codice.

Una risposta perfetta sarebbe una sintassi semplice, ma se non ce ne sono, andrò con la classe helper.

+1

ereditarietà ricorsiva, o ADL a bizzeffe (quest'ultimo richiede la modifica di tutte le basi). C++ 17 potrebbe consentire l'espansione del pacchetto nell'utilizzo di dichiarazioni - c'è un problema di EWG aperto a riguardo. –

+0

@ T.C. Ho scritto un articolo: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0195r0.html – Columbo

risposta

4

Ecco un trucco come ridurre scrittura a mano:

// U<X,Y> is a binary operation on two classes 
template<template<class,class>class U, class... Xs> struct foldr; 
template<template<class,class>class U, class X> struct foldr<U,X> : X {}; 
template<template<class,class>class U, class X, class... Xs> struct foldr<U,X,Xs...> : U<X, foldr<U,Xs...>> {}; 

// our operation inherits from both classes and declares using the member f of them  
template<class X, class Y> struct using_f : X,Y { using X::f; using Y::f; }; 

struct A { void f(int) {} }; 
struct B { void f(char) {} }; 
struct C { void f(long) {} }; 

struct D : foldr<using_f, A, B, C> {}; 


int main() { 
    D d; 
    d.f(1); 
    d.f('1'); 
    d.f(1L); 
    return 0; 
} 

Quindi dovremmo scrivere foldr una volta, quindi scrivere semplice ad hoc operazioni - using_f, using_g, using_f_g

Forse c'è un modo per ulteriormente semplificando. Lasciami pensare un po '...

Problemi correlati