基于模板参数递归重载

时间:2014-05-05 16:42:31

标签: c++

当玩好的ol' 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>

原则上,这看起来不应该是不可能的,因为所有类型信息在编译时都可用。编译器可以轻松创建所有必需的函数,因为递归必然会停止。因此问题:这可能吗?如果是这样,怎么样?

2 个答案:

答案 0 :(得分: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(); }

答案 1 :(得分:1)

您需要部分模板专业化,这是一个模板专业化,它本身又是一个模板。

使用函数模板是不可能的,但它与类有关。因此,解决方法是使用特化创建一个类模板(此处称为Magic)。在该类中,调用一个简单的(非模板)函数。

然后,函数magic转发到该类以隐藏&#34; hack&#34;:

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> > > >();
}