向后移植计时字符串文字运算符

时间:2019-12-28 09:45:40

标签: c++ c++11 c++14

我想允许使用c++14c++11一起引入的字符串文字运算符。我写了这样的东西:

namespace MYNAMESPACE {
#if __cplusplus < 201402L
constexpr std::chrono::seconds operator""s(unsigned long long int v) {
return std::chrono::seconds(v);
}
#else
using namespace std::literals::chrono_literals;
#endif
}

有可能吗?如果我很了解ADL规则,则此代码将不起作用,因为基本类型应属于全局名称空间,因此查找应在全局名称空间中执行,而不要使用我自己的名称空间。

1 个答案:

答案 0 :(得分:1)

我认为ADL对用户定义的文字不起作用。在确定构造的调用的参数类型之前,先通过非限定名称查找来查找文字运算符。

因此,必须始终将文字运算符导入到包含应该使用它的字符串文字的范围内。

在您的示例中,MYNAMESPACE中的所有内容都将能够使用operator""s(无论是来自chrono还是来自您的自定义定义。

类似地,using namespace MYNAMESPACE;using MYNAMESPACE::operator""s;范围内的每个文字都将能够使用它(使用适用using namespace的不合格名称查找的常规规则)。

唯一的问题是,如果我们严格遵守标准,则保留不以下划线开头的用户定义文字运算符,并声明它们会使程序格式错误,无需诊断。 / p>


关于查找的另一条注释:照原样,使用命名空间声明的名称查找和using namespace之间存在区别。 using namespace std::literals::chrono_literals;的行为是为了进行无限定的名称查找,就好像在全局范围内声明了文字运算符一样,而对于自定义声明则不是这样。

您可以通过使用using std::chrono_literals::operator""s;而不是using namespace std::chrono_literals;或通过在仅与{共享全局命名空间的另一个命名空间operator""s中定义自定义MYNAMESPACE2来使其表现相同。 {1}},然后在MYNAMESPACE中使用using namespace MYNAMESPACE2;

前者可能更好地模仿了MYNAMESPACE命名空间的行为,但前提是std不与文字的使用点共享任何非全局命名空间范围。

如果在 MYNAMESPACE中使用文字运算符,则后者是更好的方法,因为否则可能会掩盖导入内容,例如MYNAMESPACE(尽管它们也仅适用于C ++ 14)。