Last active
December 21, 2015 21:39
-
-
Save alexeiz/6369486 to your computer and use it in GitHub Desktop.
interface_ptr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "interfaceptr.hpp" | |
| #include <cassert> | |
| struct Interface1 {}; | |
| struct Interface2 {}; | |
| struct Interface3 {}; | |
| struct Class1 : Interface1, Interface2 {}; | |
| struct Class2 : Interface2, Interface3 {}; | |
| void test_empty() | |
| { | |
| interface_ptr<Interface1> ip1; | |
| interface_ptr<Interface1, Interface2> ip2; | |
| } | |
| void test_constructor() | |
| { | |
| // with one interface | |
| interface_ptr<Interface1> ip1(new Class1()); | |
| // with two interfaces | |
| interface_ptr<Interface1, Interface2> ip2(new Class1()); | |
| // implicit ctor | |
| interface_ptr<Interface1, Interface2> ip3 = new Class1(); | |
| // brace-style ctor | |
| interface_ptr<Interface1, Interface2> ip4{new Class1()}; | |
| // error: class doesn't implement one of the interfaces | |
| // interface_ptr<Interface1, Interface2> iperr(new Class2()); | |
| } | |
| void test_copy_ctor() | |
| { | |
| interface_ptr<Interface1, Interface2> ip1(new Class1()); | |
| interface_ptr<Interface1, Interface2> ip2(ip1); | |
| interface_ptr<Interface1, Interface2> ip3 = ip1; | |
| } | |
| void test_assignment() | |
| { | |
| interface_ptr<Interface1, Interface2> ip1(new Class1()); | |
| interface_ptr<Interface1, Interface2> ip2; | |
| ip2 = ip1; | |
| } | |
| void test_get() | |
| { | |
| Class1 * cl = new Class1(); | |
| interface_ptr<Interface1, Interface2> const ip(cl); | |
| Interface1 * ip1 = get<Interface1>(ip); | |
| assert(ip1 == cl); | |
| Interface2 * ip2 = get<Interface2>(ip); | |
| assert(ip2 == cl); | |
| // error: interface not implemented | |
| // Interface3 * ip3 = get<Interface3>(ip); | |
| } | |
| int main() | |
| { | |
| test_empty(); | |
| test_constructor(); | |
| test_copy_ctor(); | |
| test_assignment(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef INTEFACE_PTR_02028740704872 | |
| #define INTEFACE_PTR_02028740704872 | |
| #include <type_traits> | |
| namespace detail | |
| { | |
| template <typename ...Ifaces> | |
| struct interface_ptr_impl | |
| { | |
| template <typename T> | |
| constexpr | |
| interface_ptr_impl(T) {} | |
| }; | |
| template <typename Iface, typename ...Ifaces> | |
| struct interface_ptr_impl<Iface, Ifaces...> | |
| : interface_ptr_impl<Ifaces...> | |
| { | |
| using base_type = interface_ptr_impl<Ifaces...>; | |
| template <typename T> | |
| constexpr | |
| interface_ptr_impl(T ptr, | |
| typename std::enable_if<std::is_base_of<Iface, typename std::remove_pointer<T>::type>::value | |
| || std::is_same<T, std::nullptr_t>::value>::type * = 0) | |
| : base_type(ptr) | |
| , ptr_(ptr) | |
| {} | |
| template <typename GetIface> | |
| constexpr | |
| GetIface * get(typename std::enable_if<std::is_same<GetIface, Iface>::value>::type * = 0) const | |
| { | |
| return ptr_; | |
| } | |
| template <typename GetIface> | |
| constexpr | |
| GetIface * get(typename std::enable_if<!std::is_same<GetIface, Iface>::value>::type * = 0) const | |
| { | |
| return base_type::template get<GetIface>(); | |
| } | |
| Iface * ptr_; | |
| }; | |
| } // namespace detail | |
| template <typename ...Ifaces> | |
| struct interface_ptr | |
| : detail::interface_ptr_impl<Ifaces...> | |
| { | |
| using base_type = detail::interface_ptr_impl<Ifaces...>; | |
| constexpr | |
| interface_ptr() | |
| : base_type(nullptr) | |
| {} | |
| template <typename T> | |
| constexpr | |
| interface_ptr(T * ptr) | |
| : base_type(ptr) | |
| {} | |
| template <typename GetIface, typename ...GetIfaces> | |
| friend | |
| constexpr | |
| GetIface * get(interface_ptr<GetIfaces...> const & obj) | |
| { | |
| return obj.base_type::template get<GetIface>(); | |
| } | |
| }; | |
| #endif // INTEFACE_PTR_02028740704872 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment