【问题标题】:How to instantiate with other than defaulted parameters in a template template parameter如何使用模板模板参数中的默认参数以外的其他参数进行实例化
【发布时间】:2011-07-27 03:20:53
【问题描述】:

我正在努力巩固我对模板模板参数的理解。在C++ Templates the Complete Guide(Vandervoorde,Josuttis)中,他们在第 52 页有一个示例,我想使用如下图所示:

(我也在尝试学习如何在 stackoverflow 上使用 Picasa 中的图像,所以如果上述方法不起作用,这里有一个稍微详细一点的版本)

书中的原始代码

template <typename T,
          template <typename ELEM, typename ALLOC=std::allocator<ELEM> > class CONT=std::vector>
class Stack
{
    private:
        CONT<T >  elems; //Why doesn't CONT<T, ALLOC> elems; compile?
};

不向您展示如何将其用于不同的分配器。他们确实将不同的容器显示为:

Stack<int, std::deque> my_deque_stack;

我天真地尝试过:

Stack<int, std::deque<int,  std::allocator<int> >  > my_deque_int_stack;

我也尝试在私有部分将 CONT 定义为

CONT<T, ALLOC>

但这也会产生编译器错误。我想知道在我想使用双端队列但想指定不同的分配器的地方使用 Stack 模板的正确语法是什么。我在这里阅读了一些类似的帖子,这些帖子表明在周围撒了类型名或模板限定符,我尝试了几个但似乎找不到神奇的公式。

【问题讨论】:

    标签: c++ templates parameters


    【解决方案1】:

    CONT 中的参数定义实际上并没有被编译器使用。模板-模板参数CONT其实类似于一个函数,接受2种类型输入,返回一个新类型:

    // pseudo code
    type Stack(type T, type(*CONT)(type ELEM, type ALLOC = etc)) { 
       return CONT(T);
    }
    

    和正常的函数指针声明一样,名称 ELEM、ALLOC 实际上被编译器忽略

    编译器看到的只是

    template <typename T,
              template <typename E, typename = std::allocator<E> > class CONT = std::vector>
    struct Stack { ... };
    

    因此,你根本不能使用 ALLOC。


    所以要解决呢?好吧,你传递了一个额外的参数!就像普通 C++ 函数中的情况一样:

    // pseudo code
    type Stack(type T, type(*CONT)(type, type), type ALLOCATOR = etc) { 
    //                                          ^^^^^^^^^^^^^^^^^^^^
       return CONT(T, ALLOCATOR);
    }
    

    相应的实际模板声明将是

    template <typename T,
              template <typename, typename> class CONT = std::vector,
              typename ALLOCATOR = std::allocator<T> >
    //        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    struct Stack {
       ...
       CONT<T, ALLOCATOR> elems;
    };
    
    //...
    Stack<int, std::vector, std::allocator<int> > s;
    

    【讨论】:

    • 谢谢 - 我添加了 Stack > my_stack;它编译。让我想知道为什么他们在书中给出了 ELEM 和 ALLOC 的名称,然后将默认设置为 ALLOC。这让我相信应该有一种方法可以在编写的代码中指定默认分配器以外的其他内容。
    • @Tod:它使代码更易于阅读。考虑template&lt;typename,typename,typename,typename,typename&gt;template&lt;typename Key,typename Value,typename Hash,typename Eq,typename Alloc&gt;
    • 这是一个很好的观点,我猜这些名称加上默认分配器是让我陷入困境的原因。所有未命名的类型名(我在其他地方看到的)最初让我感到非常困惑。这也是我想要更好地理解这一切的原因之一。
    猜你喜欢
    • 1970-01-01
    • 2014-11-06
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    • 2020-07-10
    • 2016-10-06
    • 2018-07-04
    • 1970-01-01
    相关资源
    最近更新 更多