C++ 模板模板参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6484484/
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-28 20:13:16  来源:igfitidea点击:

Template Template Parameters

c++templates

提问by M3taSpl0it

It seems understanding template template param will kill me :(, lemme explain what misconception i made in my mind which confuses me :

似乎理解模板模板参数会杀死我:(,让我解释一下我在脑海中产生的让我感到困惑的误解:

template<class T>
class B {}; // A templated class

Here is another code :

这是另一个代码:

template<template<class X> class Z = B> // problem is in this line for me
class BB{}; 

note the line in parameter list of templated class BB , which is :

请注意模板化类 BB 的参数列表中的行,即:

template<class X> class Z = B

now what i want to ask is what stops c++ to think that Z is not a another templated class Z i.e :

现在我想问的是什么阻止 C++ 认为 Z 不是另一个模板化的类 Z 即:

template<class X> class Z{
}

rather than thinking Class Z is templated parameter itself.

而不是认为 Z 类是模板化参数本身。

Thanks a lot, i really appreciate any help to remove this misconception from my mind)

非常感谢,我真的很感激能帮助我消除这种误解)

回答by Peter Alexander

Mankarse has answered your question, but I thought I'd chime in anyway.

Mankarse 已经回答了您的问题,但我想我还是会插话的。

Template template parameters are just like normal template type parameters, except that they match templates instead of concrete types:

模板模板参数就像普通的模板类型参数一样,除了它们匹配模板而不是具体类型:

// Simple template class
template <typename Type>
class Foo
{
    Type m_member;
};

// Template template class
template <template <typename Type> class TemplateType>
class Bar
{
    TemplateType<int> m_ints;
};

If it helps, you can kind of think of them as like function pointers. Normal functions just accept arguments like normal templates just accept types. However, some functions accept function pointers which accept arguments, just like template template types accept templates that accept types:

如果有帮助,您可以将它们视为函数指针。普通函数只接受参数,就像普通模板只接受类型一样。然而,一些函数接受接受参数的函数指针,就像模板模板类型接受接受类型的模板一样:

void foo(int x)
{
    cout << x << endl;
}

void bar(void (*f)(int))
{
    f(1);
    f(2);
}

To answer your question in the comments: template template template parameters are not possible. However, the reason they are not possible is just because the standardisation committee decided that template templates were enough, probably to make lives easier for the compiler implementors. That being said, there's nothing stopping the committee from deciding that they are possible, then things like this would be valid C++:

在评论中回答您的问题:模板模板模板参数是不可能的。然而,它们不可能的原因仅仅是因为标准化委员会认为模板模板就足够了,可能是为了让编译器实现者的工作更轻松。话虽如此,没有什么能阻止委员会决定它们是可能的,那么这样的事情将是有效的 C++:

template <template <template <typename> class> class TemplateTemplateType>
class Baz
{
    TemplateTemplateType<Foo> m_foos;
};

typedef Baz<Bar> Example;
// Example would then have Bar<Foo> m_foos;
// which would have Foo<int> m_ints;

Again, you can see parallels in function pointers.

同样,您可以在函数指针中看到相似之处。

                      types <=> values
                  templates <=> functions of values
         template templates <=> functions of functions of values
template template templates <=> functions of functions of functions of values

The analogous function to Bazwould be:

类似的功能Baz是:

void baz(void (*g)(void (*f)(int)))
{
    g(foo);
}

Where would you use a template template template?

你会在哪里使用模板模板模板?

It's pretty far-fetched but I can think of one example: a really generic graph searching library.

这很牵强,但我可以想到一个例子:一个非常通用的图形搜索库。

Two common algorithms in graph searching are the depth-first search (DFS) and the breadth-first search (BFS). The implementation of the two algorithms is identical except in one regard: DFS uses a stack of nodes whereas BFS uses a queue. Ideally, we'd just write the algorithm once, with the stack/queue as an argument. Also, we'd want to specify the implementation container of the stack or queue, so that we could do something like:

图搜索中的两种常见算法是深度优先搜索(DFS)和广度优先搜索(BFS)。这两种算法的实现是相同的,除了一个方面:DFS 使用节点堆栈,而 BFS 使用队列。理想情况下,我们只需编写一次算法,并将堆栈/队列作为参数。此外,我们希望指定堆栈或队列的实现容器,以便我们可以执行以下操作:

search<Stack, Vector>( myGraph ); // DFS
search<Queue, Deque>( myGraph ); // BFS

But what is a Stack or a Queue? Well, just like in the STL a stack or a queue can be implemented with any kind of container: vectors, deques, lists etc. and could also be stacks of any element type, so our stacks or queues would have the interface:

但是什么是堆栈或队列?好吧,就像在 STL 中一样,堆栈或队列可以用任何类型的容器实现:向量、双端队列、列表等,也可以是任何元素类型的堆栈,因此我们的堆栈或队列将具有以下接口:

Stack<Vector, int> // stack of ints, using a vector implementation
Queue<Deque, bool> // queue of bools, using a deque implementation

But Vectorand Dequethemselves are template types!

但是,VectorDeque本身的模板类型!

So finally, our Stackwould be a template template like:

所以最后,我们Stack将是一个模板模板,如:

template <template <typename> class Storage, typename Element>
struct Stack
{
    void push(const Element& e) { m_storage.push_back(e); }
    void pop() { m_storage.pop_back(); }
    Storage<Element> m_storage;
};

And our searchalgorithm would then have to be a template template template!

然后我们的search算法就必须是模板模板模板!

template <template <template <typename> class, typename> class DataStructure,
          template <typename> class Storage,
          typename Graph>
void search(const Graph& g)
{
    DataStructure<Storage, typename Graph::Node> data;
    // do algorithm
}

That would be pretty intense, but hopefully you get the idea.

那会很激烈,但希望你能明白。

Remember: template template templates are not legal C++, so this whole graph search thing won't actually compile. It's just a "what if?" :)

请记住:模板模板模板不是合法的 C++,所以整个图搜索的东西实际上不会编译。这只是一个“如果呢?” :)

回答by Mankarse

This is part of the syntax of the language (which is monstrous and massively context-dependant). If template<class X> class Zoccurs in a template-parameter-list then it is interpreted as declaration of a formal parameter Zwith the kind (like a meta-type; kinds classify types in the same way types classify values) "template class taking one class argument".

这是语言语法的一部分(这是可怕的并且很大程度上依赖于上下文)。如果template<class X> class Z出现在模板参数列表中,则它被解释为Z具有种类(如元类型;种类以与类型分类值相同的方式对类型进行分类)“模板类采用一个类参数”的形式参数的声明。