为什么 class::class::class::staticClassMember() 编译(在 C++ 中)?
Why class::class::class::staticClassMember() compiles (in C++)?
我一定是遗漏了 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::
的任何计数都是允许的。
这不仅仅是一个理论问题。我想在存在子 class 的情况下使用 SFINAE 和条件编译。在基础 class 与子 class:
同名之前工作正常
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
编译)
那就是 。您可以通过在 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
也可以很好地完成。
我一定是遗漏了 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::
的任何计数都是允许的。
这不仅仅是一个理论问题。我想在存在子 class 的情况下使用 SFINAE 和条件编译。在基础 class 与子 class:
同名之前工作正常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
编译)
那就是 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
也可以很好地完成。