c++ - Template overload with mixed argument types -
i'm working on property system in c++ (c++11 ok too) classes can offer data scripting system. i'd offer various "types" of properties, simplest 1 holding value internally, this:
// simple property template<typename value> class property { public: value get() const; void set(value value); private: value m_value; } for cases, that's ok, sometimes, value calculated or has outside property object other reasons. such cases, i'd offer template this:
// complicated property template< typename value, typename valueowner, value (valueowner::*getter)(void) const, void (valueowner::*setter)(value) > class property { // stuff calling getter & setter } is there way can make 2 templates coexist without renaming 1 of them? tried specialize getter / setter template:
// complicated property // ... // simple property template<typename value> class property<value, void, nullptr, nullptr>; but compiler doesn't , complains creating pointer member function non-class type "const void". duh, of course void has no member functions.
then tried declare template sufficient arguments , specializing above templates, this:
template<typename a, typename b, typename c, typename d> class property; // simple property // ... // complicated property // ... but didn't work either, because getter / setter template doesn't expect typename third , fourth arguments, pointers member functions.
next try:
// complicated property // ... // simple property template<typename value> class property< value, property<value>, &property<value>::get, &property<value>::set >; that failed compile since compiler doesn't property<value> template inside template arguments.
alright, maybe one:
// complicated property // ... template<typename value> struct propertydummy { value get() const; void set(value); } // simple property template<typename value> class property< value, propertydummy<value>, &propertydummy<value>::get, &propertydummy<value>::set >; which yielded template argument involves template parameter(s) getter , setter template arguments. of course do.
anyway, renaming templates property , simpleproperty works me , enough. i'm curious if there's solution can write both
property<int> simpleproperty; property<int, myclass, &myclass::get, &myclass::set> complicatedproperty; and have compiler figure out template meant.
but i'm curious if there's solution [...]
yes, there is.
you use following approach. first, create dummy class template in namespace clients should not cope with:
namespace detail { template<typename t> struct dummy { t get() const { return t(); } void set(t) { } }; } then, define following primary template:
#include <type_traits> // simple property template<typename value, typename valueowner = detail::dummy<value>, value (valueowner::*getter)(void) const = &valueowner::get, void (valueowner::*setter)(value) = &valueowner::set, bool = std::is_same<valueowner, detail::dummy<value>>::value > class property { public: value get() const; void set(value value); private: value m_value; }; the value of last dummy template argument depend on whether dummy<value> passed second argument (clients should not use dummy class template, of course).
then, specialize template case when last argument false (meaning argument provided second template parameter):
// complicated property template< typename value, typename valueowner, value (valueowner::*getter)(void) const, void (valueowner::*setter)(value) > class property<value, valueowner, getter, setter, false> { // stuff calling getter & setter }; finally, use have 2 declarations proposed:
struct myclass { int get() const { return 42; } void set(int) { } }; int main() { property<int> simpleproperty; property<int, myclass, &myclass::get, &myclass::set> complicatedproperty; } here live compiling example.
Comments
Post a Comment