I must have missed something in C++ specification because I can't explain why the following code compiles successfully:
class MyClass { static void fun(); };
int main() { MyClass::MyClass::MyClass::fun(); }
Could somebody point me to the standard or just explain me the semantics? I would guess that only one MyClass::
is allowed. Two MyClass::MyClass::
should cause error. Experimenting with MS Visual C++ 2017 and GNU C++ 6.2.0 I realized that any count of MyClass::
is allowed.
It is not only a theoretical question. I wanted to use SFINAE and condition compilation with existence of a sub-class. Worked good until the base class has the same name as the sub-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
}
My question has two parts:
MyClass::MyClass::
?callWorkout<SubClass>()
? (I tried to add sizeof(typename T::SubClass)
but surprisingly it compiles also for T=SubClass
)That's the injected class name of MyClass
. And you can verify it's not T
by simply using std::is_same_v<T, typename T::SubClass>
in a SFINAE conditional.
template <class T>
auto callWorkout() -> std::enable_if_t<!std::is_same_v<T, typename T::SubClass>>
{ T::SubClass::workout(); }
If you don't need SFINAE (because you aren't trying to control overload resolution), then a static_assert
with a descriptive custom message can also do nicely.