Tag dispatch versus static methods on partially specialised classes

Solution 1:

I would like tag dispatch because:

  • Easy to extend with new tags
  • Easy to use inheritance (example)
  • It is fairly common technique in generic programming

It seems tricky to me to add third variant in second example. When you'll want to add, for example non-POD-of-PODs type you'll have to replace bool in template <typename T, bool> struct f2; with something other (int if you like =) ) and replace all struct f2<T, bool-value> with struct f2<T, another-type-value>. So that for me the second variant looks hardly extensible. Please correct me if I wrong.

Solution 2:

A readable alternative to [boost|std]::enable_if, tags and partial specialization for simple compile-time dispatch that I like is the following:

[Remember that booleans have conversion to integers, that zero-length arrays are invalid and that offending templates are discarded (SFINAE). Also, char (*)[n] is a pointer to an array of n elements.]

template <typename T> 
void foo(T, char (*)[is_pod<T>::value] = 0)
{
    // POD
}

template <typename T> 
void foo(T, char (*)[!is_pod<T>::value] = 0)
{
    // Non POD
}

It also has the advantage of not needing external classes which pollute the namespace. Now, if you want to externalize the predicate like in your question, you can do:

template <bool what, typename T>
void foo(T, char (*)[what] = 0)
{
    // taken when what is true
}

template <bool what, typename T>
void foo(T, char (*)[!what] = 0)
{
    // taken when what is false
}

Usage:

foo<std::is_pod<T>::value>(some_variable);

Solution 3:

Actually both are of the tag dispatching pattern only. Former is called tag dispatching by instance and the latter is tag dispatching by type.

Barend, the primary author of Boost.Geometry, explains both the methods and prefers the latter. This is used in Boost.Geometry extensively. Here're the advantages summarized:

  • It is unnecessary to instantiate the tag since its only purpose is to differentiate
  • It is easy to define new types and constants based on tags
  • Arguments can be reversed in the interface i.e. say distance(point, polygon); and distance(polygon, point); can both have only one implementation