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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20373466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:05:44  来源:igfitidea点击:

nested C++ template parameters for functions

c++templatesc++11

提问by bcumming

I want to have a templated function in C++, where one template parameter is itself a template of another template parameter. If that doesn't make any sense, take the following code that prints a std::vector that is templated on type T

我想在 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);

I want to further generalize this function for STL containers other than vector. But I don't know how to "nest" the template parameters such that the container is templated on type T. I have tried the following with no success

我想进一步将这个函数推广到向量以外的 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);

I am sure this has been answered here before, but I can't find the search terms to find the answer.

我确信这里之前已经回答过这个问题,但我找不到搜索词来找到答案。

EDIT: Thanks @ForEveR, your response was right on the money! All of the responses to my question observed that there is no need have the "storage" type T templated, with the following solution being adequate for the example I gave:

编辑:谢谢@ForEveR,你的回答是正确的!对我的问题的所有回答都指出,没有必要对“存储”类型 T 进行模板化,以下解决方案足以满足我给出的示例:

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

Unfortunately the actual use case that motivated the question was a little bit more complicated. The routine takes multiple containers, like this linear algebra example with a matrix and vector class:

不幸的是,引发这个问题的实际用例有点复杂。该例程采用多个容器,就像这个带有矩阵和向量类的线性代数示例:

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

Assume that both the MATRIX and VECTOR classes have to be templated on the same underlying storage class (ie. double, float, int...). The idea is that by explicitly specifying T as a template parameter, we can enforce this:

假设 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;
}

Unfortunately I am using the CUDA compiler nvcc, which doesn't have any support for C++11 constructs (I just used C++11 in my example because it is less verbose). So I can't use std::is_same and static_assert, though I suppose I could roll my own is_same (or use BOOST) easily enough. What is the "best practice" in this case, where I want to enforce the commone template parameter for the storage classes?

不幸的是,我使用的是 CUDA 编译器 nvcc,它不支持 C++11 构造(我只是在我的示例中使用了 C++11,因为它不那么冗长)。所以我不能使用 std::is_same 和 static_assert,尽管我想我可以很容易地推出我自己的 is_same(或使用 BOOST)。在这种情况下,我想为存储类强制执行 commone 模板参数的“最佳实践”是什么?

回答by ForEveR

std::vectorhas two parameters, type and allocator. Try this

std::vector有两个参数,类型和分配器。尝试这个

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

print_container(vec);

This will work for vector, list, etc., but will not work with map, set.

这适用于vector,list等,但不适用于map, set

However, since you use autoyou can use C++11 and then you can to this:

但是,因为你使用auto你可以使用 C++11 然后你可以这样:

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

or

或者

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

and of course most simple way is to do something like

当然,最简单的方法是做类似的事情

template<typename C>
void print_container(C& con)

probably with some checks for deduce, that Cis really container.

可能有一些推论检查,那C真的是容器。

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

回答by JoeG

You're better off not doing that at all; consider just templating on the container

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

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

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

If you need the stored type in the function, you can use: `typedef typename C::value_type T;

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

回答by klm123

I am not sure that I understood what you want but you can try this:

我不确定我是否理解你想要的,但你可以试试这个:

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

The point here is that usually you don't need construct like template < template V< typename T> >because whole template template V< typename T>can be generalized to type V.

这里的重点是,通常你不需要构造 liketemplate < template V< typename T> >因为整个模板template V< typename T>可以推广到 type V