如何让带requires表达式的友元函数正确访问类私有成员?
带requires表达式的友元函数访问类私有成员的问题解决
问题描述
如何使用带有requires表达式的友元函数访问类的私有成员变量?是否存在无需移除requires std::is_default_constructible_v<T>就能让代码编译通过的方法?
代码示例
#include <iostream> #include <type_traits> template<typename T> class Y { static constexpr int data = 10; template <typename U> friend U pp(); }; template<typename T> requires std::is_default_constructible_v<T> T pp() { std::cout << Y<T>::data << '\n'; return T(); } int main() { pp<int>(); return 0; }
编译报错
error: 'constexpr const int Y
::data' is private within this context
中文翻译:Y<int>::data是私有成员,在此上下文中无法访问
问题原因
你当前的代码里,类Y声明的友元是无约束的模板函数template <typename U> U pp();,但实际定义的pp函数带有requires约束。在C++中,带约束和不带约束的同名模板函数被视为不同的实体,因此带约束的pp<int>()并没有被声明为Y<int>的友元,自然无法访问私有成员data。
无需移除requires的解决方法
方法1:在友元声明中同步添加requires约束
修改类Y中的友元声明,让它和定义的pp函数约束完全一致:
#include <iostream> #include <type_traits> template<typename T> class Y { static constexpr int data = 10; // 友元声明添加对应的requires约束 template <typename U> requires std::is_default_constructible_v<U> friend U pp(); }; template<typename T> requires std::is_default_constructible_v<T> T pp() { std::cout << Y<T>::data << '\n'; return T(); } int main() { pp<int>(); return 0; }
这样友元声明与定义的模板完全匹配,编译器会正确识别友元关系,允许访问私有成员。
方法2:提前声明带约束的pp模板
先在类Y外部声明带约束的pp模板,再在类中引用该模板作为友元:
#include <iostream> #include <type_traits> // 提前声明带约束的pp模板 template<typename T> requires std::is_default_constructible_v<T> T pp(); template<typename T> class Y { static constexpr int data = 10; // 友元声明直接引用已声明的带约束模板 template <typename U> requires std::is_default_constructible_v<U> friend U pp(); }; template<typename T> requires std::is_default_constructible_v<T> T pp() { std::cout << Y<T>::data << '\n'; return T(); } int main() { pp<int>(); return 0; }
这种方式和方法1本质一致,只是通过提前声明让类Y的友元声明能精准匹配到带约束的pp模板。
内容的提问来源于stack exchange,提问作者zza
相关产品推荐
相关产品推荐

