我一定错过了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
编译)答案 0 :(得分: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
也会很好。