下面是具有某些功能的模板的代碼。幾個結構將從它繼承,每個結構將使用不同的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;
};
即使是一個確定的「沒有辦法以更好的方式表達這一點」將是有益的,如果是這樣的話。
我不知道比問題中的更好的方法。 – pts