2012-03-09 59 views
4

我想以某種方式定義一個基本模板類,以便它採用可變參數模板參數併爲每個參數定義一個虛擬方法,其中參數是參數類型。使用可變參數模板的參數定義多個方法

E.g. Base<int, bool, string>應該給我3個虛擬方法:Foo(int),Foo(bool)Foo(string)

我試過如下:

template <typename Param> 
struct BaseSingle 
{ 
    virtual void Foo(Param) {}; 
}; 

template <typename... Params> 
struct Base : public BaseSingle<Params>... 
{ 
}; 

不幸的是,富變得模糊。我無法獲得​​語法的工作。有沒有辦法?

我知道,或者,我可以從BaseSingle遞歸繼承並傳遞其餘的參數。這是否有性能影響?

+0

遞歸繼承是正常的,例如, 'std :: tuple'就是這樣實現的。我不明白你爲什麼會遇到性能問題,你的函數甚至不會相互覆蓋,也不會在運行時調用overriden成員來傳遞參數。 – doublep 2012-03-09 20:40:19

+0

[在variadic模板中使用聲明]的可能的重複(http://stackoverflow.com/questions/7870498/using-declaration-in-variadic-template) – 2012-03-09 20:46:39

+2

* std :: tuple的一些*實現使用遞歸繼承。但好的不是。 ;-) – 2012-03-09 21:51:31

回答

5

這是一個需要精確的類型匹配的建議:

#include <utility> 
#include <typeinfo> 
#include <string> 
#include <iostream> 
#include <cstdlib> 
#include <memory> 

#include <cxxabi.h> 

using namespace std; 

// GCC demangling -- not required for functionality 
string demangle(const char* mangled) { 
    int status; 
    unique_ptr<char[], void (*)(void*)> result(
    abi::__cxa_demangle(mangled, 0, 0, &status), free); 
    return result.get() ? string(result.get()) : "ERROR"; 
} 

template<typename Param> 
struct BaseSingle { 
    virtual void BaseFoo(Param) { 
    cout << "Hello from BaseSingle<" 
     << demangle(typeid(Param).name()) 
     << ">::BaseFoo" << endl; 
    }; 
}; 

template<typename... Params> 
struct Base : public BaseSingle<Params>... { 
    template<typename T> void Foo(T&& x) { 
    this->BaseSingle<T>::BaseFoo(forward<T>(x)); 
    } 
}; 

int main() { 
    Base<string, int, bool> b; 
    b.Foo(1); 
    b.Foo(true); 
    b.Foo(string("ab")); 
} 

但IMO採用遞歸繼承自己的建議聽起來更高雅。

+0

你需要一個'std :: make_unique '設施:)對於'demangle'中那個混亂的混亂。有趣的東西 – sehe 2012-03-09 21:52:51

+0

我試過這個,並且'Derived'繼承自'Base'。看起來'this-> BaseSingle :: BaseFoo'不會調用重寫的Derived'Foo',而是調用基本的,這是虛擬功能業務的重點。 – 2012-03-09 22:38:58

+0

@Msoul將它重寫爲'BaseSingle * base = this; base-> BaseFoo(轉發(x));'讓你的虛擬發送回 – je4d 2012-03-09 22:52:22