继承构造函数约束的可访问性:MSVC编译报错合理性问询
问题:MSVC对继承带requires约束的基类构造函数的私有成员访问报错是否符合标准?
在C++20环境下,继承带有requires子句约束构造函数的类模板特化时遇到问题:该类的约束基于私有静态constexpr布尔成员定义。通过using声明引入基类构造函数到派生类后,MSVC编译触发私有成员访问错误,但GCC和Clang编译正常。
相关代码
#include <type_traits> #include <cstddef> template <typename T> class container { private: static constexpr bool custom_requirement = std::is_arithmetic_v<T>; public: explicit container() = default; explicit container(size_t s) requires custom_requirement // <- 错误提示无法访问custom_requirement : m_size(s) { } auto size() const { return this->m_size; } private: size_t m_size; }; struct test : container<int> { auto extension() { return this->size() + 1; } using container<int>::container; using container<int>::operator=; }; void func() { auto t1 = test(); // 正常 auto t2 = test(3); // MSVC报错 }
MSVC错误信息关键部分
<source>(28): error C2440: '<function-style-cast>': cannot convert from 'int' to 'test' <source>(22): note: 'test::test(size_t)'约束未满足 <source>(11): note: 无法访问container<int>的私有成员custom_requirement
结论与标准说明
MSVC的报错不符合C++标准,属于编译器实现缺陷。
根据C++20标准中[class.access]章节的第6条规则:
当using声明引入基类的成员时,派生类对该成员的访问权限遵循基类中的定义;而检查该成员的约束(如requires子句)时,应当以基类的作用域为上下文进行权限验证,而非派生类作用域。
具体到这个场景:
- 基类
container<int>的构造函数约束requires custom_requirement是在基类作用域内检查的,此时custom_requirement是基类的私有成员,在基类内部可以正常访问,因此该构造函数的约束是满足的。 - 派生类
test通过using container<int>::container引入该构造函数时,不需要在派生类作用域中重新评估约束表达式的访问权限——因为约束的有效性已经在基类中确定,派生类只是继承了这个已经合法的构造函数实例。
GCC和Clang的行为符合标准,而MSVC错误地在派生类作用域中重新检查了约束表达式里的私有成员访问权限,从而触发了错误。
内容的提问来源于stack exchange,提问作者Die4Toast
相关产品推荐
相关产品推荐

