#include <iostream>
#include <typeinfo>
class B;
struct A {
decltype(auto) func(B*);
decltype(auto) func(B&);
};
template<typename T>
void size() {
std::cout << "Size of " << typeid(T).name() << ": " << sizeof(T) << '\n';
}
template<>
void size<B*>() {
std::cout << "Size of B*: " << sizeof(B*) << '\n';
}
// Error if uncommented.
//template<>
//void size<B>() {
// std::cout << "Size of B: " << sizeof(B) << '\n';
//}
class B {
friend class A;
void func() const { std::cout << "Be funky.\n"; }
};
decltype(auto) A::func(B* b) { return b->func(); }
decltype(auto) A::func(B& b) { return b.func(); }
int main() {
A a;
B b;
a.func(b);
a.func(&b);
size<B*>();
size<B>();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZWluZm8+CgpjbGFzcyBCOwoKc3RydWN0IEEgewoJZGVjbHR5cGUoYXV0bykgZnVuYyhCKik7CglkZWNsdHlwZShhdXRvKSBmdW5jKEImKTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnZvaWQgc2l6ZSgpIHsKCXN0ZDo6Y291dCA8PCAiU2l6ZSBvZiAiIDw8IHR5cGVpZChUKS5uYW1lKCkgPDwgIjogIiA8PCBzaXplb2YoVCkgPDwgJ1xuJzsKfQoKdGVtcGxhdGU8Pgp2b2lkIHNpemU8Qio+KCkgewoJc3RkOjpjb3V0IDw8ICJTaXplIG9mIEIqOiAiIDw8IHNpemVvZihCKikgPDwgJ1xuJzsKfQoKLy8gRXJyb3IgaWYgdW5jb21tZW50ZWQuCi8vdGVtcGxhdGU8PgovL3ZvaWQgc2l6ZTxCPigpIHsKLy8Jc3RkOjpjb3V0IDw8ICJTaXplIG9mIEI6ICIgPDwgc2l6ZW9mKEIpIDw8ICdcbic7Ci8vfQoKY2xhc3MgQiB7CglmcmllbmQgY2xhc3MgQTsKCQoJdm9pZCBmdW5jKCkgY29uc3QgeyBzdGQ6OmNvdXQgPDwgIkJlIGZ1bmt5LlxuIjsgfQp9OwoKZGVjbHR5cGUoYXV0bykgQTo6ZnVuYyhCKiBiKSB7IHJldHVybiBiLT5mdW5jKCk7IH0KZGVjbHR5cGUoYXV0bykgQTo6ZnVuYyhCJiBiKSB7IHJldHVybiBiLmZ1bmMoKTsgfQoKaW50IG1haW4oKSB7CglBIGE7CglCIGI7CgkKCWEuZnVuYyhiKTsKCWEuZnVuYygmYik7CgkKCXNpemU8Qio+KCk7CglzaXplPEI+KCk7Cn0=