模板模板参数

M3t*_*0it 43 c++ templates

似乎理解模板模板param会杀了我:(,lemme解释我在脑海里制造的误解让我困惑:

template<class T>
class B {}; // A templated class
Run Code Online (Sandbox Code Playgroud)

这是另一个代码:

template<template<class X> class Z = B> // problem is in this line for me
class BB{}; 
Run Code Online (Sandbox Code Playgroud)

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

template<class X> class Z = B
Run Code Online (Sandbox Code Playgroud)

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

template<class X> class Z{
}
Run Code Online (Sandbox Code Playgroud)

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

非常感谢,我真的很感激任何帮助从我的脑海中消除这种误解)

Pet*_*der 75

Mankarse回答了你的问题,但我认为无论如何我都会说话.

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

// 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;
};
Run Code Online (Sandbox Code Playgroud)

如果它有帮助,你可以将它们视为函数指针.普通函数只接受普通模板之类的参数,只接受类型.但是,有些函数接受接受参数的函数指针,就像模板模板类型接受接受类型的模板一样:

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

void bar(void (*f)(int))
{
    f(1);
    f(2);
}
Run Code Online (Sandbox Code Playgroud)

要在评论中回答您的问题:模板模板模板参数是不可能的.然而,它们不可能的原因仅仅是因为标准化委员会认为模板模板足够,可能会使编译器实现者的生活更轻松.话虽如此,没有什么可以阻止委员会决定它们是否有可能,那么这样的事情将是有效的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;
Run Code Online (Sandbox Code Playgroud)

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

                      types <=> values
                  templates <=> functions of values
         template templates <=> functions of functions of values
template template templates <=> functions of functions of functions of values
Run Code Online (Sandbox Code Playgroud)

类似的功能Baz是:

void baz(void (*g)(void (*f)(int)))
{
    g(foo);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

search<Stack, Vector>( myGraph ); // DFS
search<Queue, Deque>( myGraph ); // BFS
Run Code Online (Sandbox Code Playgroud)

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

Stack<Vector, int> // stack of ints, using a vector implementation
Queue<Deque, bool> // queue of bools, using a deque implementation
Run Code Online (Sandbox Code Playgroud)

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

最后,我们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;
};
Run Code Online (Sandbox Code Playgroud)

然后我们的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
}
Run Code Online (Sandbox Code Playgroud)

那将非常激烈,但希望你能得到这个想法.

请记住:模板模板模板不是合法的C++,因此整个图形搜索事物实际上不会编译.这只是一个"假如何?" :)


Man*_*rse 17

这是语言语法的一部分(它是怪异的,并且是大量依赖于上下文的).如果template<class X> class Z发生在template-parameter-list中,那么它被解释为Z具有类型的形式参数的声明(如元类型;种类以相同的方式分类类型类型值)"模板类采用一个类参数".