2014-04-19 31 views
1

下面是具有某些功能的模板的代碼。幾個結構將從它繼承,每個結構將使用不同的UniqueTag。也就是說,每個結構都從一個獨特的模板繼承而來。隨着天真的嘗試#1,代碼變得非常冗長。嘗試#2在冗長方面稍微好一點,但刪除了使用模板實例更改UniqueTag值所需的屬性。 #3的宏觀版本幾乎不會讓它更好。模板類的繁瑣繼承

我當然沒有C++語法大師,這讓我想知道:這可以更清楚地表達出來嗎?

嘗試#1

template <int UniqueTag, typename Verbose, typename Arguments> 
struct Base { 
    static const int tag = UniqueTag; 
    // Random example functionality 
    float data_; 
    Base(float data) : data_(data) {} 
    int do_stuff(Verbose& v, Arguments& a) { 
     return v + a; 
    } 
}; 

template <int UniqueTag, typename Verbose, typename Arguments> // once... 
struct Foo : Base<UniqueTag, Verbose, Arguments> { // twice... 
    typedef Base<UniqueTag, Verbose, Arguments> base_t; // thrice..! 
    Foo(float data) : base_t(data) {} 
    int do_it() { 
     Verbose v(10); 
     Arguments a(10); 
     return base_t::do_stuff(v, a); // must qualify dependent class name 
    } 
}; 

嘗試#2

稍微更理智的方式是模板參數存儲在所述基類。現在Foo不一定是模板類。它可以從模板繼承並通過它引用類型,而不存在依賴類的問題。 然而,它取消了Foo2的模板,這是不可接受的。

template <int UniqueTag, typename Verbose, typename Arguments> 
struct Base2 { 
    typedef Verbose verbose_t; 
    typedef Arguments arguments_t; 
    static const int tag = UniqueTag; 
    float data_; 
    Base2(float data) : data_(data) {} 
    int do_stuff(Verbose& v, Arguments& a) { 
     return v + a; 
    } 
}; 

typedef Base2<1, int, int> Foo2Base; 
struct Foo2 : Foo2Base { 
    Foo2(float data) : Foo2Base(data) {} 
    int do_it() { 
     verbose_t v(10); 
     arguments_t a(10); 
     return do_stuff(v, a); 
    } 
}; 

嘗試3

在前面的例子也是可能的宏版本,但它同時使代碼不太明顯節省了僅僅一行。

#define BASE_MACRO(name, tag, typeA, typeB) \ 
    typedef Base2<tag, typeA, typeB> name ## Base; \ 
    struct name : name ## Base 

BASE_MACRO(Foo3, 2, int, int) { 
    Foo3(float data) : Foo3Base(data) {} 
    int do_it() { 
     verbose_t v(10); 
     arguments_t a(10); 
     return do_stuff(v, a); 
    } 
}; 

// To compile all of the above. 
#include <iostream> 
int main() { 
    Foo<0, int, int> a(1.0); 
    std::cout << a.do_it() << std::endl; 
    Foo2 b(1.0); 
    std::cout << b.do_it() << std::endl; 
    Foo3 c(1.0); 
    std::cout << c.do_it() << std::endl; 
}; 

即使是一個確定的「沒有辦法以更好的方式表達這一點」將是有益的,如果是這樣的話。

+0

我不知道比問題中的更好的方法。 – pts

回答

1

那麼呢?

使do_stuff模板方法

template <int UniqueTag> 
struct Base { 
    static const int tag = UniqueTag; 
    // Random example functionality 
    float data_; 
    Base(float data) : data_(data) {} 
    template <typename Verbose, typename Arguments> 
    int do_stuff(Verbose& v, Arguments& a) { 
     return v + a; 
    } 
}; 

template <int UniqueTag, typename Verbose, typename Arguments> // once... 
struct Foo : Base<UniqueTag> { // shorter reference 
    typedef Base<UniqueTag> base_t; // shorter reference 
    Foo(float data) : base_t(data) {} 
    int do_it() { 
     Verbose v(10); 
     Arguments a(10); 
     return base_t::do_stuff(v, a); // must qualify dependent class name 
    } 
}; 

保持美孚的模板岬,同時減少了冗長

+0

我喜歡它。它讓我更多地擺弄,並且提出了其他可以在沒有這種方法的情況下工作的其他東西。 – porgarmingduod

0

經過一番擺弄周圍,我想到了我自己的簡化。只需將整個基地作爲單個模板參數傳遞即可。

template <int UniqueTag, typename Verbose, typename Arguments> 
struct Base { 
    typedef Verbose verbose_t; 
    typedef Arguments arguments_t; 
    static const int tag = UniqueTag; 
    float data_; 
    Base2(float data) : data_(data) {} 
    int do_stuff(Verbose& v, Arguments& a) { 
     return v + a; 
    } 
}; 

template <typename Base> 
struct Foo : Base { 
    Foo(float data) : Base(data) {} 
    int do_it() { 
     typename Base::verbose_t v(10); 
     typename Base::arguments_t a(10); 
     return this->do_stuff(v, a); 
    } 
}; 

Foo<Base<5, int, int> > f(1.0); 

結合@ jsantander的答案,它應該有助於各種情況。