#include <iostream>
template <typename T = void>
class Class {
public:
template <
typename U,
typename = typename std::enable_if<
// Is the use of T here allowed?
std::is_void<T>::value
|| std::is_base_of<T, U>::value
>::type
>
Class(U &&arg) {
std::cout << "Derived" << std::endl;
}
template <
typename U,
typename ...U_Rest,
typename = typename std::enable_if<
// Is the use of T here allowed?
!std::is_void<T>::value
&& !std::is_base_of<T, U>::value
>::type
>
Class(U &&arg, U_Rest &&...rest) {
std::cout << "Not Derived" << std::endl;
}
};
class Base { };
class Derived : public Base { };
int main() {
// Initialize with derived.
Class<Base> c0 { Derived() };
// Initialize with not derived.
Class<Derived> c1 { Base() };
// Use same constructor as if derived.
Class<> c2 { Derived() };
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lIFQgPSB2b2lkPgpjbGFzcyBDbGFzcyB7CnB1YmxpYzoKCXRlbXBsYXRlIDwKCQl0eXBlbmFtZSBVLAoJCXR5cGVuYW1lID0gdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8CgkJCS8vIElzIHRoZSB1c2Ugb2YgVCBoZXJlIGFsbG93ZWQ/CgkJCXN0ZDo6aXNfdm9pZDxUPjo6dmFsdWUKCQkJfHwgc3RkOjppc19iYXNlX29mPFQsIFU+Ojp2YWx1ZQoJCT46OnR5cGUKCT4KCUNsYXNzKFUgJiZhcmcpIHsKCQlzdGQ6OmNvdXQgPDwgIkRlcml2ZWQiIDw8IHN0ZDo6ZW5kbDsKCX0KCQoJdGVtcGxhdGUgPAoJCXR5cGVuYW1lIFUsCgkJdHlwZW5hbWUgLi4uVV9SZXN0LAoJCXR5cGVuYW1lID0gdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8CgkJCS8vIElzIHRoZSB1c2Ugb2YgVCBoZXJlIGFsbG93ZWQ/CgkJCSFzdGQ6OmlzX3ZvaWQ8VD46OnZhbHVlCgkJCSYmICFzdGQ6OmlzX2Jhc2Vfb2Y8VCwgVT46OnZhbHVlCgkJPjo6dHlwZQoJPgoJQ2xhc3MoVSAmJmFyZywgVV9SZXN0ICYmLi4ucmVzdCkgewoJCXN0ZDo6Y291dCA8PCAiTm90IERlcml2ZWQiIDw8IHN0ZDo6ZW5kbDsKCX0KfTsKCmNsYXNzIEJhc2UgeyB9OwpjbGFzcyBEZXJpdmVkIDogcHVibGljIEJhc2UgeyB9OwoKaW50IG1haW4oKSB7CgkvLyBJbml0aWFsaXplIHdpdGggZGVyaXZlZC4KCUNsYXNzPEJhc2U+IGMwIHsgRGVyaXZlZCgpIH07CgkvLyBJbml0aWFsaXplIHdpdGggbm90IGRlcml2ZWQuCglDbGFzczxEZXJpdmVkPiBjMSB7IEJhc2UoKSB9OwoJLy8gVXNlIHNhbWUgY29uc3RydWN0b3IgYXMgaWYgZGVyaXZlZC4KCUNsYXNzPD4gYzIgeyBEZXJpdmVkKCkgfTsKfQo=