c++ - Is this "Tag Dispatching"? -


say have code:

void bara() { } void barb() { }  void fooa() {   // duplicate code...   bara();   // more duplicate code... }  void foob() {   // duplicate code...   barb();   // more duplicate code... }  int main() {   fooa();   foob(); } 

and want remove duplicate code between fooa , foob use number of dynamic techniques such passing in bool parameter, passing function pointer or virtual methods if wanted compile time technique this:

struct { }; struct b { };  template<typename tag> void bar(); template<> void bar<a>() { } template<> void bar<b>() { }  template<typename tag> void foo() {   // duplicate code   bar<tag>();   // more duplicate code }  int main() {   foo<a>();   foo<b>(); } 

where have introduced 2 empty "tag" classes indicate bar use , templated foo , bar based on tag class. seems trick. questions:

  1. does technique have name? example of "tag dispatching"? read tag dispatching different , involves function overloading tag parameter. tag may have come typedef in trait class.
  2. is there more idomatic compile-time technique of achieving same thing?

edit: possibility use function overloading of bar instead of template specialization , pass tag class parameter:

struct { }; struct b { };  void bar(a) { } void bar(b) { }  template<typename tag> void foo() {   // duplicate code   bar(tag());   // more duplicate code }  int main() {   foo<a>();   foo<b>(); } 

this isn't tag dispatching. rightly said in question, that'd if used compile time trait of a , b distinguish between two, , use select between 2 different overloads.

an example of tag dispatch how std::advance typically implemented. function's signature is

template< class inputit, class distance > void advance( inputit& it, distance n ); 

it can advanced n positions in single operation if meets requirements of randomaccessiterator. lesser iterators must advance it in loop. implementation similar following:

namespace detail {   template<class inputit, class distance>   void advance(inputit& it, distance n, std::random_access_iterator_tag)    {     += n;   }    template<class inputit, class distance>   void advance(inputit& it, distance n, std::bidirectional_iterator_tag)    {     if(n < 0) {       while(n++) --it;     } else {       while(n--) ++it;     }   }    template<class inputit, class distance>   void advance(inputit& it, distance n, std::input_iterator_tag)    {     assert(n >= 0);     while(n--) ++it;   } }  template< class inputit, class distance > void advance( inputit& it, distance n ) {   detail::advance(it, n,                    typename std::iterator_traits<inputit>::iterator_category()); } 

i don't know of specific name you're doing. it's example of how 1 follow dry principle.

if bar took instance of a , b argument, i'd implement differently. instead of making bar function template, , providing specializations, i'd let overload resolution job me.

void bar(a const&) { ... } void bar(b const&) { ... } 

but since that's not case, providing explicit specializations seems right way this.


Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

thorough guide for profiling racket code -