2014-05-05 49 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