C ++三重嵌套模板参数的正确语法

时间:2015-08-02 05:09:13

标签: c++ templates

我很困惑为什么下面的代码被编译器拒绝了。有些帮忙吗?

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

2 个答案:

答案 0 :(得分: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;
}

查看您的代码,不清楚哪一个适合您。

<强>更新

以下代码不起作用

#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 :(得分: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