why do we need an extra type ( special_ / general_ ) in this method
They are used only so that the modifyNormal function is overloaded with various implementations. What is especially important in them is that special_ uses the IS-A relation, since it inherits from general_ . In addition, the transform function always calls modifyNormal overload, which is of type special_ , see the next part.
what helps us typename int_<decltype(Lhs::normal)>::type = 0
This is a template argument with a default value. A default value is present, so the transform function should not indicate it, which is important because this template parameter is not present in another modifyNormal function. In addition, this template parameter is added only for calling SFINAE.
http://en.cppreference.com/w/cpp/language/sfinae
When replacing the inferred type for the template parameter, the specialization is discarded from the overload set, and does not cause a compilation error.
So, if a crash occurs, the modifyNormal function using the special_ type is removed from the set of overloads for consideration. This causes the modifyNormal function to modifyNormal type general_ , and since special_ IS-A general_ type is still working.
If a replacement failure does not occur, then the modifyNormal function using the special_ type will be used because it matches better.
Note. The general_ type is a struct , so inheritance is public by default, which allows you to use IS-A relationships without using the public keyword.
Edit:
Can you comment on why we primarily use the complex typename int_<decltype(Lhs::normal)>::type mechanism typename int_<decltype(Lhs::normal)>::type ?
As stated above, this is used to trigger the behavior of SFINAE. However, it is not very difficult when you break it. In this case, he wants to create an instance of the int_ structure for some type T and has a data type :
int_<T>::type
Since this is used in the template, the typename keyword needs to be added, see When is the "typename" keyword required? .
typename int_<T>::type
Finally, what is the actual type used to instantiate the int_ structure? This is defined by decltype(Lhs::normal) , which tells the type for Lhs::normal . If the Lhs type has a normal data member, then everything will succeed. However, if this is not the case, the replacement will fail, and the importance of this is explained above.