为什么 class::class::class::staticClassMember() 编译(在 C++ 年)

Why class::class::class::staticClassMember() compiles (in C++)?

本文关键字:class C++ 编译 staticClassMember 为什么      更新时间:2023-10-16

我一定错过了C++规范中的某些内容,因为我无法解释为什么以下代码可以成功编译:

class MyClass { static void fun(); };
int main() { MyClass::MyClass::MyClass::fun(); }

有人可以指出我的标准或只是解释我的语义吗?我猜只允许一个MyClass::。两个MyClass::MyClass::应该会导致错误。在尝试 MS Visual C++ 2017 和 GNU C++ 6.2.0 时,我意识到允许任何MyClass::计数。

这不仅仅是一个理论问题。我想使用 SFINAE 和条件编译与子类的存在。在基类与子类具有相同的名称之前运行良好:

template <class T> void callWorkout() { T::SubClass::workout(); }
struct X { struct SubClass { static void workout(); }; };
struct Y { /*empty*/ };
struct SubClass { static void workout(); };
int main() {
  callWorkout<X>();  // works fine - compiled
  callWorkout<Y>();  // works "fine" - not compiled, no SubClass in Y
  callWorkout<SubClass>();  // ooops? - still compiled, there is no 'SubClass' in SubClass
}

我的问题分为两部分:

  • MyClass::MyClass::的确切语义是什么?
  • 如何修复上面的示例以不编译callWorkout<SubClass>()?(我试图添加sizeof(typename T::SubClass)但令人惊讶的是它也为T=SubClass编译(

这是注入的类名 MyClass .您可以通过简单地在 SFINAE 条件中使用std::is_same_v<T, typename T::SubClass>来验证它是否T

template <class T>
auto callWorkout() -> std::enable_if_t<!std::is_same_v<T, typename T::SubClass>>
{ T::SubClass::workout(); }

如果您不需要 SFINAE(因为您没有尝试控制重载解析(,那么带有描述性自定义消息的static_assert也可以很好地完成。