.
.
( ). , ,
Impl.
class InvalidImpl {};
void bar()
{
InvalidImpl invalid;
CRTP_Interface<InvalidImpl> crtp_invalid;
#if 0
invalid.Foo();
crtp_invalid.Foo();
#endif
}
, , :
#include <cstdint>
#include <type_traits>
#define HAS_MEM_FUNC(name, Prototype, func) \
template<typename U> \
struct name { \
typedef std::uint8_t yes; \
typedef std::uint16_t no; \
template <typename T, T> struct type_check; \
template <typename T = U> \
static yes &chk(type_check<Prototype, &T::func> *); \
template <typename > static no &chk(...); \
static constexpr bool value = sizeof(chk<U>(0)) == sizeof(yes); \
}
HAS_MEM_FUNC(has_Foo, void (T::*)(), Foo);
template <typename T>
struct check_Interface :
std::integral_constant<bool, has_Foo<T>::value >
{};
#define CHECK_INTERFACE(T) static_assert(check_Interface<T>::value, #T " doesn't respect the interface")
#define CHECK_NOT_INTERFACE(T) static_assert(!check_Interface<T>::value, #T " does respect the interface")
:
class Interface {
public:
virtual void Foo() = 0;
};
class Child_Impl final : public Interface {
public:
void Foo() override {};
};
#if 0
class Child_InvalidImpl final : public Interface {};
#endif
template <class I>
class CRTP_Interface : public I
{
public:
void Foo() { I::Foo(); }
};
class Impl { public: void Foo(); };
class InvalidImpl {};
CHECK_INTERFACE(Interface);
CHECK_INTERFACE(Child_Impl);
CHECK_INTERFACE(Impl);
CHECK_INTERFACE(CRTP_Interface<Impl>);
CHECK_NOT_INTERFACE(InvalidImpl);
CHECK_INTERFACE(CRTP_Interface<InvalidImpl>);
. , final class Child final : public Interface.
, :
void bar(Child& child) { child.Foo(); }
( bar ):
void bar(Interface& child) { child.Foo(); }
, :
void Interface::Bar() { Foo(); }
, Foo.
, :
template<class Derived>
void Interface<Derived>::Bar() { static_cast<Derived*>(this)->Foo(); }