На ФП ответили, но я хочу вмешаться, потому что непосредственной причиной проблемы является не рекурсия, как утверждают другие. Самая простая причина, по которой это не сработает, заключается в том, что шаблоны классов не типов. Это шаблоны. Точно так же шаблоны функций также не являются функциями. Так что все это бессмысленно:
template<typename T> int function_template(int);
typedef int function_type(int);
void eats_a_function(function_type&); // needs a reference to function
std::vector< std::vector > vec0; // std::vector is not a type
std::vector< std::list > vec1; // std::list is not a type
eats_a_function(function_template); // function_template is not a function
Обратите внимание, что в случае vec1
, std::list
не связано с std::vector
. Шаблон полностью определен (при условии включения заголовка) в момент его создания. Это все еще не будет работать.
Вместо этого работает следующее:
std::vector< std::vector<int> > vec2; // std::vector<int> is a type
std::vector< std::list<double> > vec3; // std::list<double> is a type
eats_a_function(function_template<long>); // function_template<long> is a function
Обратите внимание, что в случае с vec2 нормально передать экземпляр самого шаблона.
Для справки, игрушечное решение проблемы с игрушкой при написании шаблона, который ссылается на себя, используя пресловутый слой косвенности:
// expects a template that expects a type
template<template<class> class T> struct indirection {};
// forward decl. for defaulting the parameter
template<typename T> struct recursive;
// template that expects a type
template<typename T = indirection<recursive> > struct recursive {};
Не очень мощный, учитывая несколько вещей, которые возможны с шаблоном (параметр T
внутри indirection
). Конечно, можно написать метафункцию в стиле rebind
, которая возвращает экземпляр T
.