为啥 std:set (带有单个冒号)可以编译?

Posted

技术标签:

【中文标题】为啥 std:set (带有单个冒号)可以编译?【英文标题】:Why can std:set (with a single colon) compile?为什么 std:set (带有单个冒号)可以编译? 【发布时间】:2018-08-28 03:01:21 【问题描述】:

不小心写了

std::set<string> keys;

作为:

std:set<string> keys;

但奇怪的是,Visual Studio 2013 仍然可以编译。

为什么会这样?

其实keys不仅是定义的,而是后来作为一组字符串使用的,比如

if(keys.find(keystr)==keys.end())
    keys.insert(keystr);
    toret.push_back(tempv);

【问题讨论】:

std: 被解释为labelgoto。见:en.cppreference.com/w/cpp/language/goto 【参考方案1】:

在块范围内,一个标识符后跟一个冒号会引入一个标签。因此,您的陈述相当于:

set<string> keys;

除了它带有标签std并且可以通过语句goto std;跳转到。

由于某种原因,名称 set 为编译器所知 --- 可能您使用了 using namespace std;using std::set; 或类似的东西,或者您在某处定义了自己的 set 类型。

【讨论】:

这是避免using namespace std;using std::set;的另一个原因 using namespace std/using std::set 提出了很好的论据,但我不确定这是其中之一......主要论据通常是命名空间是为了防止冲突,但如果有一个非标准的“集合”要与之碰撞,那么std: set&lt;...&gt; 可能是有效的。通常的做法是将任何此类 using 声明限制为另一个名称空间/函数,但这个问题很容易在该范围内发生。我更愿意期望在重写std::chrono::high_resolution_clock 等时出现错字而不是这个标签错字(我第一次看到这样的错误)。【参考方案2】:

在第二种情况下,std 是一个标签。这与在 case 语句中拼错 default 相同。

【讨论】:

以上是关于为啥 std:set (带有单个冒号)可以编译?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 std::set::find 不提供提示迭代器?

为啥 std::remove 需要 const 版本的迭代器? [复制]

为啥 std::unordered_set 不将 CComBSTR 类型作为键?

为啥使用包含冒号的 URL 被视为“潜在危险请求”?

std::set 插入器不尊重自定义比较器。 (可能的编译器错误?)

g++5 中 std::unordered_set 编译错误的不完整类型,在 clang++ 中编译