2015-08-02 2 views
1

Я смущен, почему код ниже отклоняется компилятором. Помогите пожалуйста?Правильный синтаксис C++ для параметра тройного вложенного шаблона

template<template<template<class> class> class Ptr, 
template<class> class Container, class T> 
inline void print(Ptr<Container<T>> l) { 
    std::cout << '['; 
    for (auto it = l->begin(); it != l->end() - 1; ++it) { 
     std::cout << *it << ", "; 
    } 
    std::cout << l->back() << ']' << std::endl; 
} 
+0

@ TheParamagneticCroissant Где я использовал его в качестве имени переменной? – xiver77

+0

@ TheParamagneticCroissant, то в чем же проблема? – xiver77

+0

@ TheParamagneticCroissant Нет ничего плохого в 'template class'. Это параметр шаблона без имени шаблона. –

ответ

2

я запутался о том, что работает и что не в ответе @RSahu и решает ли это проблему в целом.

Но, вдохновленный этим, я получаю следующее решение. Это просто использует тот факт, что класс шаблона класса может быть переменным. Так, например, теперь он совместим с std::vector<T, A> или другими классами (контейнеры hopefuly), которые имеют более или менее параметры шаблона. На самом деле полезно сделать то же самое с параметром Ptr, чтобы он также был совместим с std::unique_ptr, который принимает больше параметров шаблона, чем std::shared_ptr.

http://coliru.stacked-crooked.com/a/40d43526ed77eb9d

#include <iostream> 
#include <vector> 
#include <memory> 

template<template<class...> class Ptr, template<class...> class Container, class T> 
inline void f(Ptr<Container<T>> p) { 
    std::cout << "bla" << std::endl; 
} 

int main() { 
    f(std::make_shared<std::vector<int>>()); 
} 

Примечание: сказав, что, я думаю, что есть более эффективные способы, чтобы ограничить типы аргументов, чем принуждая модели.

Например, это может быть альтернативой:

template<class PtrContainerT, typename = decltype(std::declval<PtrContainerT>()->back())> //probably pretty much constrains the intended use 
inline void f(PtrContainerT&& p) { 
    using T = typename PtrContainerT::element_type::value_type; //in case you need to know T 
    std::cout << "bla" << std::endl; 
} 

http://coliru.stacked-crooked.com/a/fbe43aab94364764

или даже больше, до точки (хотя и не на 100% эквивалент):

template<class PtrContainerT, typename T = typename PtrContainerT::element_type::value_type> //probably pretty much constrains the intended use 
inline void f(PtrContainerT&& p) { 
    std::cout << "bla" << std::endl; 
} 

Использование std::decay<PtrContainerT>::...etc при необходимости ,

2

Я могу придумать следующие два пути решения проблемы.

template <template <template <class> class> class Ptr, 
      template<class> class Container, class T> 
inline void print(Ptr<Container> l) { 
       // ^^^ Not Ptr<Container<T>> 
    std::cout << '['; 
    for (auto it = l->begin(); it != l->end() - 1; ++it) { 
     std::cout << *it << ", "; 
    } 
    std::cout << l->back() << ']' << std::endl; 
} 

или

template <template<class> class Ptr, 
     // One less level of template for Ptr 
      template<class> class Container, class T> 
inline void print(Ptr<Container<T>> l) { 
       // Containe<T> is a class 
    std::cout << '['; 
    for (auto it = l->begin(); it != l->end() - 1; ++it) { 
     std::cout << *it << ", "; 
    } 
    std::cout << l->back() << ']' << std::endl; 
} 

Глядя на ваш код, не ясно, какой из них будет работать для вас.

Update

Следующий код не работает

#include <vector> 
#include <memory> 

template<template<class> class Ptr, template<class> class Container, class T> 
inline void f(Ptr<Container<T>> p) {} 

int main() { 
    f(std::make_shared<std::vector<int>>()); 
} 

так std::vector определяется как:

template< 
    class T, 
    class Allocator = std::allocator<T> 
> class vector; 

Это не

template< 
    class T, 
> class vector; 

Это работает:

template<template<class> class Ptr, template<class> class Container, class T> 
inline void f(Ptr<Container<T>> p) {} 

template <typename T> using MyVector = std::vector<T>; 

int main() { 
    f<std::shared_ptr, MyVector, int>(std::make_shared<MyVector<int>>()); 
} 

Это также работает:

template<template<class> class Ptr, template<class> class Container, class T> 
inline void f(Ptr<Container<T>> p) {} 

template <typename T> struct Foo {}; 

int main() { 
    f(std::make_shared<Foo<int>>()); 
} 
+1

Параметр 'T' не используется в этом примере, но мне это нужно. Я пытаюсь передать 'std :: shared_ptr >' в качестве аргумента, например. – xiver77

+0

Я получаю следующее сообщение об ошибке: примечание: шаблон-кандидат игнорируется: сбой подстановки [with Ptr = shared_ptr]: аргумент шаблона шаблона имеет другой шаблон параметров, чем соответствующий шаблонный шаблонный параметр ' – xiver77

+0

@ xiver77, в этом случае вы можете использовать второе решение. –

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