2014-04-19 27 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的答案,它应该有助于各种情况。