#include <type_traits>
class A {};
class B: public A {};
class C: public B {};
class X {};
template<typename T, typename Base,
typename = typename std::enable_if<
std::is_base_of<std::decay_t<Base>, std::decay_t<T>>::value>::type>
void foo(T& tp, const Base* bp);
int main()
{
A a; B b; C c; X x;
foo(c, &a);
foo(b, &a);
foo(a, &a);
foo(c, &b);
foo(c, &c);
foo(x, &a); // invalid and produces compiler error
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKY2xhc3MgQSB7fTsKCmNsYXNzIEI6IHB1YmxpYyBBIHt9OwoKY2xhc3MgQzogcHVibGljIEIge307CgpjbGFzcyBYIHt9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgQmFzZSwKICAgIHR5cGVuYW1lID0gdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8CiAgICAgICAgc3RkOjppc19iYXNlX29mPHN0ZDo6ZGVjYXlfdDxCYXNlPiwgc3RkOjpkZWNheV90PFQ+Pjo6dmFsdWU+Ojp0eXBlPgp2b2lkIGZvbyhUJiB0cCwgY29uc3QgQmFzZSogYnApOwoKaW50IG1haW4oKQp7CglBIGE7IEIgYjsgQyBjOyBYIHg7Cglmb28oYywgJmEpOwoJZm9vKGIsICZhKTsKCWZvbyhhLCAmYSk7CgkKCWZvbyhjLCAmYik7CgkKCWZvbyhjLCAmYyk7CgkKCWZvbyh4LCAmYSk7IC8vIGludmFsaWQgYW5kIHByb2R1Y2VzIGNvbXBpbGVyIGVycm9yCn0=
prog.cpp: In function 'int main()':
prog.cpp:27:11: error: no matching function for call to 'foo(X&, A*)'
foo(x, &a); // invalid and produces compiler error
^
prog.cpp:27:11: note: candidate is:
prog.cpp:14:6: note: template<class T, class Base, class> void foo(T&, const Base*)
void foo(T& tp, const Base* bp);
^
prog.cpp:14:6: note: template argument deduction/substitution failed:
prog.cpp:12:5: error: no type named 'type' in 'struct std::enable_if<false, void>'
typename = typename std::enable_if<
^