├── .gitignore ├── LICENSE.md ├── README.md └── polyvar.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2016 Barrett Adair 2 | 3 | Boost Software License - Version 1.0 - August 17th, 2003 4 | 5 | Permission is hereby granted, free of charge, to any person or organization 6 | obtaining a copy of the software and accompanying documentation covered by 7 | this license (the "Software") to use, reproduce, display, distribute, 8 | execute, and transmit the Software, and to prepare derivative works of the 9 | Software, and to permit third-parties to whom the Software is furnished to 10 | do so, all subject to the following: 11 | 12 | The copyright notices in the Software and this entire statement, including 13 | the above license grant, this restriction and the following disclaimer, 14 | must be included in all copies of the Software, in whole or in part, and 15 | all derivative works of the Software, unless such copies or derivative 16 | works are solely in the form of machine-executable object code generated by 17 | a source language processor. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # polyvar 2 | polymorphism with value semantics (based on std::variant) 3 | 4 | Example: 5 | 6 | ```cpp 7 | #include "polyvar.hpp" 8 | #include 9 | 10 | struct A { 11 | char do_something() { return 'A'; } 12 | int do_something_else(int x) { return x; } 13 | }; 14 | 15 | struct B { 16 | char do_something() { return 'B'; } 17 | int do_something_else(int x) { return x + 1; } 18 | }; 19 | 20 | struct C { 21 | char do_something() { return 'C'; } 22 | int do_something_else(int x) { return x + 2; } 23 | }; 24 | 25 | // Define a variant template with self-visiting member 26 | // functions to emulate a base class 27 | DEFINE_POLYVAR(my_var, 28 | (do_something) 29 | (do_something_else) 30 | ); 31 | 32 | using var = my_var; 33 | 34 | int main () { 35 | 36 | var v = A{}; 37 | std::cout << v.do_something() << std::endl; 38 | std::cout << v.do_something_else(0) << std::endl; 39 | 40 | v = B{}; 41 | std::cout << v.do_something() << std::endl; 42 | std::cout << v.do_something_else(1) << std::endl; 43 | 44 | v = C{}; 45 | std::cout << v.do_something() << std::endl; 46 | std::cout << v.do_something_else(2) << std::endl; 47 | } 48 | 49 | ``` 50 | -------------------------------------------------------------------------------- /polyvar.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 Barrett Adair 3 | 4 | Distributed under the Boost Software License, Version 1.0. 5 | (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 6 | */ 7 | 8 | #ifndef POLYVAR_HPP 9 | #define POLYVAR_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define POLYVAR_USE_BOOST 18 | //#define POLYVAR_USE_MAPBOX 19 | 20 | #if defined POLYVAR_USE_BOOST 21 | # include 22 | # define POLYVAR_VARIANT_IMPL boost::variant 23 | # define POLYVAR_USING \ 24 | using POLYVAR_VARIANT_IMPL::variant; \ 25 | using POLYVAR_VARIANT_IMPL::operator=; \ 26 | using POLYVAR_VARIANT_IMPL::which; \ 27 | using POLYVAR_VARIANT_IMPL::empty; \ 28 | using POLYVAR_VARIANT_IMPL::type; \ 29 | /**/ 30 | # define POLYVAR_VISIT_IMPL boost::apply_visitor 31 | #elif defined POLYVAR_USE_MAPBOX 32 | // include it your damn self 33 | # define POLYVAR_VARIANT_IMPL mapbox::util::variant 34 | # define POLYVAR_VISIT_IMPL mapbox::util::apply_visitor 35 | # define POLYVAR_USING \ 36 | using POLYVAR_VARIANT_IMPL::variant; \ 37 | using POLYVAR_VARIANT_IMPL::operator=; \ 38 | using POLYVAR_VARIANT_IMPL::which; \ 39 | using POLYVAR_VARIANT_IMPL::empty; \ 40 | using POLYVAR_VARIANT_IMPL::type; \ 41 | #else 42 | # include 43 | # define POLYVAR_VARIANT_IMPL std::variant 44 | # define POLYVAR_VISIT_IMPL std::visit 45 | // TODO - check these 46 | # define POLYVAR_USING \ 47 | using POLYVAR_VARIANT_IMPL::variant; \ 48 | using POLYVAR_VARIANT_IMPL::operator=; \ 49 | using POLYVAR_VARIANT_IMPL::which; \ 50 | using POLYVAR_VARIANT_IMPL::empty; \ 51 | using POLYVAR_VARIANT_IMPL::type; \ 52 | /**/ 53 | #endif 54 | 55 | #define DEFINE_POLYVAR(name, ...) \ 56 | template \ 57 | struct name : public POLYVAR_VARIANT_IMPL { \ 58 | \ 59 | using base = POLYVAR_VARIANT_IMPL; \ 60 | POLYVAR_USING \ 61 | \ 62 | BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(__VA_ARGS__), POLYVAR_MEMFNS, __VA_ARGS__) \ 63 | } \ 64 | /**/ 65 | 66 | #define POLYVAR_MEMFNS(z, i, seq) POLYVAR_MEMFNS_I(BOOST_PP_SEQ_ELEM(i,seq)) 67 | 68 | #define POLYVAR_MEMFNS_I(name) \ 69 | template \ 70 | constexpr decltype(auto) name(Args&&... args) { \ 71 | return POLYVAR_VISIT_IMPL([&](auto& v){ \ 72 | return v.name( \ 73 | static_cast(args)...);}, *this); \ 74 | } \ 75 | /**/ 76 | 77 | #endif // #ifndef POLYVAR_HPP 78 | --------------------------------------------------------------------------------