2014-05-05 68 views
0

當好醇」 c++玩弄我開始懷疑是否有可能超載基於一個封閉的模板的模板功能。在第一層看起來這是可以實現的,但是,這怎麼可以遞歸地完成呢?這樣的下面僞C++代碼超載遞歸基於模板參數

#include <iostream> 
#include <vector> 
#include <map> 

template <typename T> void magic(){ 
    std::cout << "Called magic<T>" << std::endl; 
} 

template <typename std::vector<T> > void magic(){ 
    std::cout << "Called magic<std::vector<T> >" << std::endl; 
    magic<T>(); 
} 

template <typename std::map<T,U> > void magic(){ 
    std::cout << "Called magic<std::map<T,U> >" << std::endl; 
    magic<T>(); 
    magic<U>(); 
} 


int main() { 
    magic<std::vector<std::map<std::string,std::vector<int> > > >(); 
} 

產生類似:

Called magic<std::vector<T> > 
Called magic<std::map<T,U> > 
Called magic<T> 
Called magic<std::vector<T> > 
Called magic<T> 

原則上,這看起來並不像它應該是不可能的,因爲所有類型的信息可在編譯時。編譯器可以輕鬆創建所有必需的函數,因爲遞歸必然會停止。因此,問題:這可能嗎?如果是這樣,怎麼樣?

+0

你想C++ 98? – cubuspl42

回答

3

簡單的分工應該做的伎倆,但請記住,你不能專注函數模板部分,所以你需要一箇中間類模板:

template <typename> void magic(); 

template <typename T> 
struct Impl 
{ 
    static void f() { std::cout << "Primary template\n"; } 
}; 

template <typename T, typename A> 
struct Impl<std::vector<T, A>> 
{ 
    static void f() { std::cout << "A vector\n"; magic<T>(); } 
}; 

template <typename K, typename T, typename P, typename A> 
struct Impl<std::map<K, T, P, A>> 
{ 
    static void f() { std::cout << "A map\n"; magic<K>(); magic<T>(); } 
}; 

template <typename T> void magic() { Impl<T>::f(); } 
+0

它是C++ 11(因爲'>>'),我不確定這是否重要。 – cubuspl42

+0

[現場演示](http://coliru.stacked-crooked.com/a/c9945033c8e1106c)。 –

+0

我知道我忘記了一些事情......無法決定接受哪個答案,因爲兩種解決方案都是平等的。所以我投擲了一枚硬幣,你很幸運:-) – elemakil

1

你需要模板偏特,即是一個模板專業化,它本身又是一個模板。

這對於函數模板來說是不可能的,但它是與類一起使用的。所以解決方法是創建一個專業化的類模板(這裏叫Magic)。在該類中,調用一個簡單的(非模板)函數。

然後,功能magic轉發到該類爲了隱瞞 「黑客」:

Live demo of this code snippet

#include <iostream> 
#include <vector> 
#include <map> 

// Forward declaration of the magic function: 
template <typename> void magic(); 

// General case: 
template <typename T> 
struct Magic { 
    static void m(){ 
     std::cout << "Called magic<T>" << std::endl; 
    } 
}; 

// Vector case: 
template <typename T> 
struct Magic<std::vector<T> > { 
    static void m(){ 
     std::cout << "Called magic<std::vector<T> >" << std::endl; 
     magic<T>(); 
    } 
}; 

// Map case: 
template <typename T, typename U> 
struct Magic<std::map<T,U> > { 
    static void m(){ 
     std::cout << "Called magic<std::map<T> >" << std::endl; 
     magic<T>(); 
     magic<U>(); 
    } 
}; 

// Implementation of the magic function: 
template <typename T> 
void magic() { 
    std::cout << "Forwarding..." << std::endl; 
    Magic<T>::m(); 
} 

int main() { 
    magic<std::vector<std::map<std::string,std::vector<int> > > >(); 
} 
+0

我知道我忘了某件事......由於兩種解決方案都是平等的,所以無法決定接受哪個答案。所以我扔了一枚硬幣,不幸的是它出現了尾巴。儘管如此,謝謝你的答案! :-) – elemakil