2016-02-18 9 views
6

基底クラスがそれを提供しない場合、メソッドの埋め込みについてどう思いますか?私はそれが提供されている場合は、基本クラスのメソッドを再利用したいと思います。テンプレート提供の基底クラスを変更する

例:

#include <iostream> 
struct Base0 { }; 
struct Base1 { void m() { std::cout<<"Base1\n"; } }; 

template<typename T> 
struct Derived : public T { 
    //if T doesn't provide m, define it here, otherwise reuse the base class method 
    void m(){ /*? std::cout<<"Derived\n"; ?*/ } 
}; 

int main(){ 
    Derived<Base0> d0; 
    d0.m(); //should print "Derived" 
    Derived<Base1> d1; 
    d1.m(); //should print "Base1" 
} 
+0

を行うことができますとにかく注文する。 Derivedは型であり、Derivedが 'm()'関数を持っている限り、常に基本関数 'm()'を上書きします。 –

+0

継承、仮想関数、テンプレートというコンセプトを組み合わせています。全体的にそれはコードのにおいです。テンプレートを持ち、継承と仮想関数を避けます。 –

答えて

8

、あなたが本当にそれをこのようにやりたいならば、あなたはコールとの問題を抱えて、まあ

template<typename T> 
struct Derived : public T { 
private: 
    template <typename U = T> 
    auto m_impl(int) -> decltype(std::declval<U&>().m()){ this->U::m(); } 

    template <typename U = T> 
    void m_impl(...) { std::cout<<"Derived\n"; } 

public: 
    void m() { m_impl(0); } 
}; 

Demo

2

一般的であるために、あなたは別の署名の下で、とにかく関数を定義する必要があります

template<typename T> 
struct Derived : public T 
{ 
    auto m(std::false_type) { std::cout<<"Derived\n"; } 
}; 

次にあなたがチェックするためにthis threadに与えられた方法を使用することができます基底クラスに関数があるかどうかm()

template <typename...> 
using void_t = void; 

template <typename T, template <typename> class D, typename = void> 
struct detect : std::false_type {}; 

template <typename T, template <typename> class D> 
struct detect<T, D, void_t<D<T>>> : std::true_type {}; 

template <typename T> 
using has_m = decltype(std::declval<T>().m()); 

最後に、あなたはすでに述べAslay Berbyとして

0

template<typename T> 
struct Derived : public T 
{ 
    auto m(std::true_type) { return T::m(); } 
    auto m(std::false_type) { std::cout<<"Derived\n"; } 
    auto m() { return m(detect</* const */ T, has_m>{}); } 
           ^^^^^^^^^^ 
           //if m() is const 
}; 

として、これはおそらく、あなたが行きたい道ではないことを使用することができます。特性やポリシーベースの設計などを実装したい場合は、以下のコードを探しているかもしれません。実際、このようなデザインはかなり一般的に使用されており、慣用的な価値もあります。

#include <iostream> 
using namespace std; 

struct StandardTraits {void foo() {cout << "standard" << endl;}}; 

struct Traits1 {void foo() {cout << "traits1" << endl;}}; 
struct Traits2 {void foo() {cout << "traits2"<< endl;}}; 

template<typename T = StandardTraits> 
class SomeClass 
{ 
public: 
    typedef T Traits; 

    void useTraits() {traits.foo();} 

private: 
    Traits traits; 
}; 

int main() { 

    SomeClass<> x; 
    SomeClass<Traits1> y; 
    SomeClass<Traits2> z; 

    x.useTraits(); 
    y.useTraits(); 
    z.useTraits(); 

    return 0; 
} 

// output: 
// standard 
// traits1 
// traits2 

も参照してください:SFINAEでhttps://en.wikipedia.org/wiki/Policy-based_design

関連する問題