【问题标题】:Why class::class::class::staticClassMember() compiles (in C++)?为什么 class::class::class::staticClassMember() 编译(在 C++ 中)?
【发布时间】:2019-03-25 07:15:14
【问题描述】:

我一定错过了 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&lt;SubClass&gt;()? (我尝试添加sizeof(typename T::SubClass),但令人惊讶的是它也为T=SubClass 编译)

【问题讨论】:

标签: c++ language-lawyer static-methods sfinae name-lookup


【解决方案1】:

那是injected class name of MyClass。您可以通过在 SFINAE 条件中简单地使用 std::is_same_v&lt;T, typename T::SubClass&gt; 来验证它不是 T

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

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

【讨论】:

    猜你喜欢
    • 2012-08-03
    • 1970-01-01
    • 2016-10-05
    • 2019-07-30
    • 2013-05-01
    • 1970-01-01
    • 2013-11-13
    • 2016-08-28
    • 1970-01-01
    相关资源
    最近更新 更多