Clang++下C++友元用户自定义字面量声明失败问题咨询
C++用户定义字面量友元声明问题分析
问题代码
namespace ns { class MyClass { private: int value; MyClass(int val) : value(val) {} friend MyClass operator"" _myudl(unsigned long long int val); // Friend UDL declaration friend MyClass (::operator"" _myudl) (unsigned long long int val); // not working too; public: int getValue() const { return value; } }; } // Definition of the friend UDL outside the class ns::MyClass operator"" _myudl(unsigned long long int val) { return ns::MyClass(static_cast<int>(val)); } int main() { ns::MyClass obj = 100_myudl; // Using the friend UDL return 0; }
编译报错:使用clang++ -std=c++20编译时失败,提示调用私有构造函数,说明友元声明未生效。
编译器行为正确性
Clang的行为符合C++标准,是正确的。
原因在于:类内的友元声明friend MyClass operator"" _myudl(...)默认会将该用户定义字面量(UDL)函数声明到当前类所在的ns命名空间中,但实际定义的UDL函数属于全局命名空间(返回类型是ns::MyClass不影响函数本身的命名空间归属)。这两个是完全独立的函数实体,因此类的友元关系无法作用到全局的UDL函数上,导致它无法访问私有构造函数。
部分编译器(如GCC)可能会接受这段代码,但这属于非标准扩展行为,不符合C++规范。
仅修改友元声明的修复方法
需要明确指定友元是全局命名空间下的UDL函数,将友元声明修改为:
friend MyClass ::operator"" _myudl(unsigned long long int val);
或者简化参数类型写法:
friend MyClass ::operator"" _myudl(unsigned long long);
添加::前缀后,类会明确将全局命名空间下的operator"" _myudl函数标记为友元,此时全局UDL函数就能正常访问MyClass的私有构造函数,编译即可通过。
内容的提问来源于stack exchange,提问作者Ashcoll Ash
相关产品推荐
相关产品推荐

