堆栈模板参数

Stack Template Arguments

本文关键字:参数 堆栈      更新时间:2023-10-16

关注模板参数

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

stack<int, vector<int>> myStack;

我知道第二个模板参数表示堆栈的底层数据结构。但是为什么下一行没有给出编译时错误呢?

stack<int, vector<string>> myStack;

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

从功能上讲,它就像一堆字符串元素一样工作。

您正在做的是未定义的行为。尽管如此,我还是要解释一下为什么它看起来很好

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

在这里,我们关注的是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的别名。未使用用于T(在您的情况下为int(的类型。因此,一切似乎都起作用。

但是即使这适用于您的情况和特定编译器,但实际上是不允许的:

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

您可以在此处找到此报价的来源。

来自文档:

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

未定义的行为意味着它可能会编译,甚至可能工作,或者可能会擦除你的硬盘。

它是如何失败的,如果失败了,则取决于实现。

如果非要我猜测,我会想象您的实现正在丢弃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.