如何在同一作用域无歧义地使用两个同名用户定义字面量(UDL)?
如何在同一作用域无歧义使用同名用户定义字面量(UDL)
先看这段代码:两个命名空间里定义了同名的UDL后缀_x,分别返回不同的自定义类型:
namespace foo { struct x{ unsigned long long i; }; namespace literals { constexpr foo::x operator""_x(unsigned long long i) { return { i }; } } } namespace bar { struct x{ unsigned long long i; }; namespace literals { constexpr bar::x operator""_x(unsigned long long i) { return { i }; } } }
有没有办法在同一作用域里无歧义地用这两个UDL?普通类型或函数可以直接用全限定名解决,比如:
std::vector<std::pair<foo::x, bar::x>> v = { { foo::x{ 3 }, bar::x{ 14 } }, };
但UDL不行——除非把它当普通函数调用foo::literals::operator""_x(3),但这样就失去了UDL简写的意义。试了命名空间别名也没用,比如这种写法是错误的:
namespace f = foo::literals; namespace b = bar::literals; std::vector<std::pair<foo::x, bar::x>> v = { { 3f::_x, 14b::_x }, };
目前我会用辅助函数或立即调用函数表达式(IIFE)来构造容器,不过想知道有没有办法不放弃UDL的简写形式。
可行解决方案
1. 给UDL定义不同的后缀别名(最推荐)
直接给两个UDL封装新的、不同后缀的字面量运算符,完全保留简写风格:
// 给foo的_x定义别名_foo_x constexpr foo::x operator""_foo_x(unsigned long long i) { return foo::literals::operator""_x(i); } // 给bar的_x定义别名_bar_x constexpr bar::x operator""_bar_x(unsigned long long i) { return bar::literals::operator""_x(i); } // 使用时完全符合UDL的简写习惯 std::vector<std::pair<foo::x, bar::x>> v = { {3_foo_x, 14_bar_x}, {2_foo_x, 7_bar_x} };
这种方法可读性强,完全消除歧义,且不需要额外作用域处理,适合频繁使用的场景。
2. 利用局部作用域的using声明
如果只是偶尔使用,可以在小作用域内单独引入对应命名空间的literals,比如用lambda创建局部作用域:
std::vector<std::pair<foo::x, bar::x>> v = { // 第一个元素:只引入foo的literals,用3_x []{ using namespace foo::literals; return std::pair{3_x, bar::x{14}}; }(), // 第二个元素:只引入bar的literals,用14_x []{ using namespace bar::literals; return std::pair{foo::x{3}, 14_x}; }() };
这种方法不需要额外定义函数,适合零散使用的场景,只是写法稍显繁琐。
3. 显式类型转换配合局部using(简化版)
如果只需要在一行里混用,也可以用花括号创建临时作用域:
std::vector<std::pair<foo::x, bar::x>> v = { { []{ using namespace foo::literals; return 3_x; }(), []{ using namespace bar::literals; return 14_x; }() }, { []{ using namespace foo::literals; return 5_x; }(), []{ using namespace bar::literals; return 9_x; }() } };
内容的提问来源于stack exchange,提问作者Dominik Kaszewski
相关产品推荐
相关产品推荐

