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

Popular posts from this blog

node.js - Bad Request - node js ajax post -

Why does Ruby on Rails generate add a blank line to the end of a file? -

keyboard - Smiles and long press feature in Android -