#define OPTION 1 // OPTION 2 : broken, OPTION 1 : works
#include <iostream>
#include <type_traits>
using namespace std;
template <typename T,typename Enable=void>
struct child;
template <typename T>
struct base
{
typedef T type;
#if OPTION ==1
struct base_tag{};
#endif
};
#if OPTION ==2
template <typename T>
struct child < T, typename std::enable_if < std::is_base_of< base<typename T::type>, T>::value>::type>
{
const char* value = "specialization";
};
#else
template <typename T>
struct child < T, std::void_t<typename T::base_tag> >
{
const char* value = "specialization";
};
#endif
template <typename T>
struct dervived : base<T>
{
child<dervived> child_;
typedef T type;
};
int main() {
std::cout << dervived<int>().child_.value << std::endl;
return 0;
}
I2RlZmluZSBPUFRJT04gMSAvLyBPUFRJT04gMiA6IGJyb2tlbiwgT1BUSU9OIDEgOiB3b3JrcwoKI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsdHlwZW5hbWUgRW5hYmxlPXZvaWQ+CnN0cnVjdCBjaGlsZDsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpzdHJ1Y3QgYmFzZQp7Cgl0eXBlZGVmIFQgdHlwZTsJCgkKCSNpZiBPUFRJT04gPT0xCglzdHJ1Y3QgYmFzZV90YWd7fTsKCQoJI2VuZGlmCgp9OwoKCiNpZiBPUFRJT04gPT0yCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpzdHJ1Y3QgY2hpbGQgPCBULCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZiA8IHN0ZDo6aXNfYmFzZV9vZjwgYmFzZTx0eXBlbmFtZSBUOjp0eXBlPiwgVD46OnZhbHVlPjo6dHlwZT4KewoKCSBjb25zdCBjaGFyKiB2YWx1ZSA9ICJzcGVjaWFsaXphdGlvbiI7Cn07CiNlbHNlCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IGNoaWxkIDwgVCwgc3RkOjp2b2lkX3Q8dHlwZW5hbWUgVDo6YmFzZV90YWc+ID4KewoKCSBjb25zdCBjaGFyKiB2YWx1ZSA9ICJzcGVjaWFsaXphdGlvbiI7Cn07CgojZW5kaWYKCgoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnN0cnVjdCBkZXJ2aXZlZCA6IGJhc2U8VD4KewoJCWNoaWxkPGRlcnZpdmVkPiBjaGlsZF87CgkJdHlwZWRlZiBUIHR5cGU7CQp9OwoKCgppbnQgbWFpbigpIHsKCQoJCglzdGQ6OmNvdXQgPDwgZGVydml2ZWQ8aW50PigpLmNoaWxkXy52YWx1ZSA8PCBzdGQ6OmVuZGw7CglyZXR1cm4gMDsKfQ==