为什么 operator""s 被隐藏在命名空间中?

28
为了使用 `std::string` 的 operator""s,您需要执行 using namespace std::string_literals。但是,未以 _ 开头的用户自定义字面值是保留的,因此可能的冲突不能成为借口。另一个 operator""s 来自于 std::chrono,但那是针对 int 字面值的,因此也不存在冲突。
这是什么原因?

哦,我记得看过一个关于这个话题的讲座,可能是在CppCon或Boostcon上,但我不记得为什么会这样了。 - Borgleader
虽然我不知道确切的原因,但避免使用如此短的后缀来污染全局命名空间似乎是合理的。 - Aleph
1
@Borgleader https://www.youtube.com/watch?v=dTeKf5Oek2c 这是视频开头的部分。 - user3920237
@remyabel,你是我的救星。非常感谢你为我找到它! - Borgleader
1个回答

25

将字面量放入命名空间中的原因实际上有两个:

  1. 认为用户仅仅是为了获取相应的字面量而使用 using namespace std; 是不可取的。将字面量声明在特定的命名空间中不会引起这个问题。
  2. 根据领域的不同,使用 s 作为其他内容的后缀可能是可取的。已经有另一个后缀 s 表示秒,但它们并不会真正冲突。

STL's CppCon 2014 talk 的视频(由评论中的 remyable 发布),Stephan T. Lavavej 解释了 C++14 中字面量的整体设计,很明显它们应该在全局命名空间中!相反,标准库中的字面量后缀存在于一系列 inline 命名空间层次结构中,使用户可以对可用的字面量进行细粒度控制。例如,字符串的字面量后缀声明如下(21.3 [string.classes] 第1段):

namespace std {
    inline namespace literals {
        inline namespace string_literals {
            string operator"" s(char const* str, size_t len);
        }
    }
}

这个inline命名空间的层次结构使得用户可以获得适当的字面后缀选择:

  • using namespace std; - 您可以获得标准C++库中的所有内容,包括字面后缀,而无需任何限定。
  • using namespace std::literals; - 您可以获得标准C++库中定义的所有字面后缀。
  • using namespace std::string_literals; - 您可以获得适用于字符串的所有字面后缀。
  • using namespace std::literals::string_literals; - 是的,您可以这样做,但您真的不应该这样做:这相当于using namespace std::string_literals;

显然,如果委员会认为仅仅通过污染全局命名空间来添加字面后缀是可行的想法,那么它不会付出那么多的努力,尽管它们甚至不能与任何用户字面后缀冲突。


我不太确定。用户非标准库代码无法声明 operator""s,或者可以吗? - milleniumbug
2
@milleniumbug:正确的做法是用户定义字面量需要以 _ 开头。冲突解决并不是针对用户代码,而是其他标准库类。目前我想不出一个令人信服的例子,但是一旦我们拥有了网络库,使用 "127.0.0.1:80"s 创建一个套接字可能很酷。...另外一个争论点,不希望通过 using namespace std; 污染代码也是有道理的:据我所知,你无法为字面量运算符单独使用 using 声明。 - Dietmar Kühl
1
@milleniumbug 提议的 string_view 是另一个潜在的 ""s 字面量的候选者,尽管它过去也使用了 ""sv 来避免冲突。(在当前草案中,它根本没有字面运算符。)无法预测哪种解决方案(例如不同命名空间中的并发 ""s 字面量或其他方式)将被保留。 - Luc Danton
7
这个设计决策的反面就是,在头文件中使用标准用户定义字面量没有合理方法,因为这会违反“头文件中不使用using指令”的指导方针。 - Casey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接