#include <type_traits>
#include <iostream>
// interface class
class A
{
public:
virtual void foo() = 0;
virtual ~A() {}
};
namespace detail
{
// an helper for traits
template <typename T>
decltype(T{}, std::cout << T{}, std::true_type{})
helper_has_default_constructor_and_foo(int);
template <typename T>
std::false_type helper_has_default_constructor_and_foo(...);
// the traits
template <typename T>
using has_default_constructor_and_foo = decltype(helper_has_default_constructor_and_foo<T>(0));
// genaral case (so when traits is false)
template <typename T, typename = has_default_constructor_and_foo<T>>
struct C : public A {};
// specialization when traits is true
template <typename T>
struct C<T, std::true_type> : public A
{
void foo() override { std::cout << T{}; }
};
}
template <typename T>
class B : public detail::C<T>
{
};
// concrete classes
// will work on it's own
typedef B<std::string> C;
class D : public B<void>
{
public:
// B<void>::foo won't instantiate on it's own
// so we provide help here
void foo() override {}
};
int main()
{
//B<void> b; // error as expected
B<int> b;
C c;
D d;
b.foo(); // 0
c.foo(); // empty string
d.foo(); // nothing
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8aW9zdHJlYW0+CgovLyBpbnRlcmZhY2UgY2xhc3MKY2xhc3MgQQp7CnB1YmxpYzoKICAgIHZpcnR1YWwgdm9pZCBmb28oKSA9IDA7CiAgICB2aXJ0dWFsIH5BKCkge30KfTsKCm5hbWVzcGFjZSBkZXRhaWwKewogICAgLy8gYW4gaGVscGVyIGZvciB0cmFpdHMKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUPgogICAgZGVjbHR5cGUoVHt9LCBzdGQ6OmNvdXQgPDwgVHt9LCBzdGQ6OnRydWVfdHlwZXt9KQogICAgaGVscGVyX2hhc19kZWZhdWx0X2NvbnN0cnVjdG9yX2FuZF9mb28oaW50KTsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICAgIHN0ZDo6ZmFsc2VfdHlwZSBoZWxwZXJfaGFzX2RlZmF1bHRfY29uc3RydWN0b3JfYW5kX2ZvbyguLi4pOwoKICAgIC8vIHRoZSB0cmFpdHMKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUPgogICAgdXNpbmcgaGFzX2RlZmF1bHRfY29uc3RydWN0b3JfYW5kX2ZvbyA9IGRlY2x0eXBlKGhlbHBlcl9oYXNfZGVmYXVsdF9jb25zdHJ1Y3Rvcl9hbmRfZm9vPFQ+KDApKTsKCiAgICAvLyBnZW5hcmFsIGNhc2UgKHNvIHdoZW4gdHJhaXRzIGlzIGZhbHNlKQogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lID0gaGFzX2RlZmF1bHRfY29uc3RydWN0b3JfYW5kX2ZvbzxUPj4KICAgIHN0cnVjdCBDIDogcHVibGljIEEge307CgogICAgLy8gc3BlY2lhbGl6YXRpb24gd2hlbiB0cmFpdHMgaXMgdHJ1ZQogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgICBzdHJ1Y3QgQzxULCBzdGQ6OnRydWVfdHlwZT4gOiBwdWJsaWMgQQogICAgewogICAgICAgIHZvaWQgZm9vKCkgb3ZlcnJpZGUgeyBzdGQ6OmNvdXQgPDwgVHt9OyB9CiAgICB9OwoKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmNsYXNzIEIgOiBwdWJsaWMgZGV0YWlsOjpDPFQ+CnsKfTsKCi8vIGNvbmNyZXRlIGNsYXNzZXMKLy8gd2lsbCB3b3JrIG9uIGl0J3Mgb3duCnR5cGVkZWYgQjxzdGQ6OnN0cmluZz4gQzsKCmNsYXNzIEQgOiBwdWJsaWMgQjx2b2lkPgp7CnB1YmxpYzoKICAgIC8vIEI8dm9pZD46OmZvbyB3b24ndCBpbnN0YW50aWF0ZSBvbiBpdCdzIG93bgogICAgLy8gc28gd2UgcHJvdmlkZSBoZWxwIGhlcmUKICAgIHZvaWQgZm9vKCkgb3ZlcnJpZGUge30KfTsKCmludCBtYWluKCkKewogICAgLy9CPHZvaWQ+IGI7IC8vIGVycm9yIGFzIGV4cGVjdGVkCiAgICBCPGludD4gYjsKICAgIEMgYzsKICAgIEQgZDsKICAgIAogICAgYi5mb28oKTsgLy8gMAogICAgYy5mb28oKTsgLy8gZW1wdHkgc3RyaW5nCiAgICBkLmZvbygpOyAvLyBub3RoaW5nCn0K