为什么class :: class :: class :: staticClassMember()编译(用C ++编写)?

问题描述 投票:3回答:1

我一定错过了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
c++ language-lawyer static-methods sfinae name-lookup
1个回答
6
投票

这就是injected class name of MyClass。你可以通过简单地在SFINAE条件下使用T来验证它不是std::is_same_v<T, typename T::SubClass>

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

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

© www.soinside.com 2019 - 2024. All rights reserved.