13

Klasa pochodna ukrywa nazwę przeciążenia ustalonym z klasy bazowej, jeśli klasa pochodna ma taką samą nazwę zdefiniowane, ale zawsze możemy przedstawić, że przeciążenie cofnięty z wykorzystaniem-deklaracji:C++ - Jak wprowadzić zestaw przeciążeniowy z variadic number of bases.

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

ale co jeśli Wprowadzam wszystkie zestawy przeciążeniowe z klas bazowych variadic? Czy mógłbym napisać coś takiego?

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

ja uważane za pomocą klasy pomocnika jak:

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; 
}; 

I to działa. Ale wymaga to dużo pisania (oczywiście mogę używać makra, ale staram się używać funkcji kompilacji C++, gdy tylko jest to możliwe), a kiedy chcę wprowadzić więcej metod, muszę dużo zmienić w tym fragmencie kodu.

Doskonałą odpowiedzią byłaby prosta składnia, ale jeśli jej nie ma, przejdę do klasy pomocnika.

+1

Rekursywne dziedziczenie, lub mnóstwo ADL (to ostatnie wymaga modyfikacji wszystkich baz). C++ 17 może pozwolić na rozszerzenie paczki przy korzystaniu z deklaracji - jest to kwestia otwarta na poziomie EWG. –

+0

@ T.C. Napisałem artykuł: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0195r0.html – Columbo

Odpowiedz

4

Oto sztuczka jak zmniejszyć pisma:

// 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; 
} 

Więc powinniśmy napisać foldr raz, a następnie napisać prosty ad-hoc operacji - using_f, using_g, using_f_g

Może istnieje sposób, aby dalsze uproszczenie. Pozwól mi trochę pomyśleć ...