#include <stdio.h>
#define INTERFACE(Name) \
template <typename ImplType> \
struct Name
#define INTERFACE_FUNC(Ret, Name, Args) \
template <typename... TArgs> \
inline Ret Name (TArgs... args) { \
static constexpr Ret (ImplType::*ptr) Args = &ImplType::Name; \
return ((static_cast<ImplType *>(this))->*ptr)(args...); \
}
INTERFACE(Iface) {
INTERFACE_FUNC(int, Foo, (int x, int y))
INTERFACE_FUNC(void, Bar, (double a))
};
struct Impl : Iface<Impl> {
int Foo (int x, int y)
{
return x + y;
}
void Bar (double a)
{
printf("%f\n", a);
}
void NotExposed ()
{
}
};
template <typename ImplType>
void UseViaIface (Iface<ImplType> *iface)
{
int res = iface->Foo(2, 4);
printf("%d\n", res);
iface->Bar(3.4);
// Compile error because NotExposed is not part of the interface.
//iface->NotExposed();
}
int main ()
{
Impl impl;
UseViaIface(&impl);
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CgojZGVmaW5lIElOVEVSRkFDRShOYW1lKSBcCnRlbXBsYXRlIDx0eXBlbmFtZSBJbXBsVHlwZT4gXApzdHJ1Y3QgTmFtZQoKI2RlZmluZSBJTlRFUkZBQ0VfRlVOQyhSZXQsIE5hbWUsIEFyZ3MpIFwKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIFRBcmdzPiBcCmlubGluZSBSZXQgTmFtZSAoVEFyZ3MuLi4gYXJncykgeyBcCiAgICBzdGF0aWMgY29uc3RleHByIFJldCAoSW1wbFR5cGU6OipwdHIpIEFyZ3MgPSAmSW1wbFR5cGU6Ok5hbWU7IFwKICAgIHJldHVybiAoKHN0YXRpY19jYXN0PEltcGxUeXBlICo+KHRoaXMpKS0+KnB0cikoYXJncy4uLik7IFwKfQoKSU5URVJGQUNFKElmYWNlKSB7CiAgICBJTlRFUkZBQ0VfRlVOQyhpbnQsIEZvbywgKGludCB4LCBpbnQgeSkpCiAgICBJTlRFUkZBQ0VfRlVOQyh2b2lkLCBCYXIsIChkb3VibGUgYSkpCn07CgpzdHJ1Y3QgSW1wbCA6IElmYWNlPEltcGw+IHsKICAgIGludCBGb28gKGludCB4LCBpbnQgeSkKICAgIHsKICAgICAgICByZXR1cm4geCArIHk7CiAgICB9CiAgICAKICAgIHZvaWQgQmFyIChkb3VibGUgYSkKICAgIHsKICAgICAgICBwcmludGYoIiVmXG4iLCBhKTsKICAgIH0KICAgIAogICAgdm9pZCBOb3RFeHBvc2VkICgpCiAgICB7CiAgICB9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSW1wbFR5cGU+CnZvaWQgVXNlVmlhSWZhY2UgKElmYWNlPEltcGxUeXBlPiAqaWZhY2UpCnsKICAgIGludCByZXMgPSBpZmFjZS0+Rm9vKDIsIDQpOwogICAgcHJpbnRmKCIlZFxuIiwgcmVzKTsKICAgIAogICAgaWZhY2UtPkJhcigzLjQpOwogICAgCiAgICAvLyBDb21waWxlIGVycm9yIGJlY2F1c2UgTm90RXhwb3NlZCBpcyBub3QgcGFydCBvZiB0aGUgaW50ZXJmYWNlLgogICAgLy9pZmFjZS0+Tm90RXhwb3NlZCgpOwp9CgppbnQgbWFpbiAoKQp7CiAgICBJbXBsIGltcGw7CiAgICBVc2VWaWFJZmFjZSgmaW1wbCk7CiAgICByZXR1cm4gMDsKfQoK