函数的嵌套C ++模板参数

时间:2013-12-04 10:56:33

标签: c++ templates c++11

我想在C ++中使用模板化函数,其中一个模板参数本身就是另一个模板参数的模板。如果这没有任何意义,请使用以下代码打印在类型T上模板化的std :: vector

template <typename T>
void print_vector(std::vector<T> &vec)
{
    for(auto v: vec)
        std::cout << v << " ";
    std::cout << std::endl;
}
...
std::vector<double> vec(5);
...
print_vector(vec);

我想进一步推广除vector之外的STL容器的这个函数。但我不知道如何“嵌套”模板参数,以便容器在类型T上模板化。我尝试了以下但没有成功

template <typename T, template <typename TT> V>
void print_container(V<T> &con)
{
    for(auto c: con)
        std::cout << c << " ";
    std::cout << std::endl;
}
...
std::vector<double> vec(5);
...
print_container(vec);

我确信之前已经回答过,但我找不到搜索字词来找到答案。

编辑:谢谢@ForEveR,您的回复是正确的!对我的问题的所有回答都观察到没有必要将“存储”类型T模板化,以下解决方案对于我给出的示例是足够的:

template <typename C>
void print_container(C &con)
{
    for(auto v: con)
        std::cout << v << " ";
    std::cout << std::endl;
}

不幸的是,推动这个问题的实际用例有点复杂。该例程需要多个容器,例如带有矩阵和向量类的线性代数示例:

template <typename MATRIX, typename VECTOR>
void mat_vec_multiply(const MATRIX &A, const VECTOR &x, VECTOR &y)
{
    // implement y = A*x;
}

假设MATRIX和VECTOR类都必须在同一个底层存储类上进行模板化(即double,float,int ......)。我们的想法是,通过明确指定T作为模板参数,我们可以强制执行:

template < typename T,
           template<typename> class MATRIX,
           template<typename> class VECTOR>
void mat_vec_multiply(const MATRIX<T> &A, const VECTOR<T> &x, VECTOR<T> &y)
{
    // implement y = A*x;
}

不幸的是我使用的是CUDA编译器nvcc,它对C ++ 11构造没有任何支持(我在我的例子中只使用了C ++ 11,因为它不那么详细)。所以我不能使用std :: is_same和static_assert,虽然我想我可以轻松地滚动自己的is_same(或使用BOOST)。在这种情况下,什么是“最佳实践”,我想为存储类强制执行commone模板参数?

3 个答案:

答案 0 :(得分:20)

std::vector有两个参数,type和allocator。 试试这个

template <typename T, typename Alloc, template <typename, typename> class V>
void print_container(V<T, Alloc> &con)
{
}

print_container(vec);

这适用于vectorlist等,但不适用于mapset

但是,由于你使用auto,你可以使用C ++ 11,然后就可以了:

template <typename T, template <typename, typename...> class V, typename... Args>
void print_container(V<T, Args...> &con)

template <template <typename, typename...> class V, typename... Args>
void print_container(V<Args...> &con)

当然,最简单的方法是做一些像

这样的事情
template<typename C>
void print_container(C& con)

可能有一些推断检查,C实际上是容器。

template<typename C>
auto print_container(C& con) -> decltype(con.begin(), void())

答案 1 :(得分:3)

你最好不要那样做;考虑只是模板化容器

template <typename C>
void print_container(const C& container)
{

    for(auto v: container)
        std::cout << v << " ";
    std::cout << std::endl;
}

如果你需要函数中存储的类型,你可以使用:`typedef typename C :: value_type T;

答案 2 :(得分:2)

我不确定我理解你想要什么,但你可以试试这个:

template <typename V>
void print_vector(V &vec)
{
    for(auto v: vec)
        std::cout << v << " ";
    std::cout << std::endl;
}
...
std::vector<double> vec(5);
...
print_vector(vec);

这里的要点是,通常您不需要像template < template V< typename T> >这样的构造,因为整个模板template V< typename T>可以推广到V类型。