关注模板参数
我可以这样创建一个堆栈(来自标准库的适配器类模板)对象:
stack<int, vector<int>> myStack;
我知道第二个模板参数表示堆栈的底层数据结构。但是为什么以下代码行不会在编译时出现错误?
stack<int, vector<string>> myStack;
请注意,我声明了一个包含
int
类型元素的栈,但同时我声明了底层数据结构来保存string
元素。
从功能上讲,它的作用就像是一个字符串元素的栈。
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.
Container::value_type == string
,而T == int
。 - Bill Lynch