堆栈模板参数

时间:2016-08-06 17:20:16

标签: c++ c++11

专注于模板参数

我可以像这样创建一个堆栈(来自标准库的适配器类模板)对象,

stack<int, vector<int>> myStack;

我知道第二个模板参数意味着堆栈的底层数据结构。但是为什么以下行不会产生编译时错误?

stack<int, vector<string>> myStack;

请注意,我声明堆栈包含int类型的元素,但同时我声明基础数据结构包含string元素。

从功能上讲,它就好像是一堆字符串元素。

3 个答案:

答案 0 :(得分:6)

您正在做的是未定义的行为。不过,我将解释为什么它似乎工作正常。

容器适配器std::stack<T, TContainer>包含多个类型符号,这些符号是常用类型的别名。有一个列表here

我们这里关注的是std::stack::value_type。它基本上决定了方法std::stack::push和朋友期望的类型:

void push( const value_type& value );

我们也可以看到它是如何定义的:

using value_type = typename TContainer::value_type

因此,所有操作中使用的类型实际上仅基于第二种类型TContainer!在您的情况下,这是vector<string>::value_type,因此value_type将是string的别名。您的案例中用于Tint的类型未使用。 因此,所有似乎都能正常工作。

即使在您的情况下使用您的特定编译器,但实际上不允许这样做:

  

如果T与Container :: value_type的类型不同,则行为未定义。 (自C ++ 17起)

您可以找到此引文的来源here

答案 1 :(得分:1)

来自文档:

  

T - 存储元素的类型。如果T与Container :: value_type的类型不同,则行为未定义。 (自C ++ 17起)

未定义的行为意味着它可能会编译,甚至可能会起作用,或者它可能会擦除您的硬盘驱动器。

如果失败,如果失败,则取决于实现。

答案 2 :(得分:0)

如果我不得不猜测,我会想到您的实现会丢弃int模板参数,而只是使用Container::value_type

一旦我们进入C ++ 17,这将是明确非法的。有些编译器已经不喜欢这段代码..

例如:

#include <stack>
#include <string>
#include <vector>

int main() {
    std::stack<int, std::vector<std::string>> s;
    s.push(3);
}

无法在OS X(clang,libc ++,c ++ 11)下编译:

blah.cc:7:7: error: no matching member function for call to 'push'
    s.push(3);
    ~~^~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stack:194:10: note: 
      candidate function not viable: no known conversion from 'int' to 'const value_type' (aka
      'const std::__1::basic_string<char>') for 1st argument
    void push(const value_type& __v) {c.push_back(__v);}
         ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stack:197:10: note: 
      candidate function not viable: no known conversion from 'int' to 'value_type' (aka 'std::__1::basic_string<char>') for
      1st argument
    void push(value_type&& __v) {c.push_back(_VSTD::move(__v));}
         ^
1 error generated.