2013-12-04 3 views
16

Я хочу иметь шаблонную функцию в C++, где один параметр шаблона сам является шаблоном другого параметра шаблона. Если это не имеет никакого смысла, возьмите следующий код, который печатает зЬй :: вектора, который шаблонный по типу ТВложенные параметры шаблона C++ для функций

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

Я хочу, чтобы в дальнейшем обобщить эту функцию для других, чем вектор 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); 

, я уверен, это было до того здесь ответа, но Я не могу найти поисковые запросы, чтобы найти ответ.

EDIT: Спасибо @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 классы должны быть шаблонными на тот же базовом класс хранения (т.е. дважды, поплавок, ква ...). Идея заключается в том, что путем явного указания Т в качестве параметра шаблона, мы можем применять это:

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 для классов хранения?

ответ

17

std::vector имеет два параметра, тип и распределитель. Попробуйте

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

print_container(vec); 

Это будет работать для vector, list и т.д., но не будет работать с map, set.

Однако, так как вы используете 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()) 
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.

3

Вам лучше не делать этого вообще; рассмотреть только шаблонированию на контейнере

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

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

Если вам нужен сохраненный тип в функции, вы можете использовать: `ЬурейеГо имяТип C :: value_type T;

Смежные вопросы