Tag dispatch versus static methods on partially specialised classes

一个人想着一个人 提交于 2019-11-28 02:53:59

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.

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);

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

I know this is an old question with the answer already accepted, but this might be a viable alternative:

template<typename T>
std::enable_if_t<std::is_pod<T>::value> f(T pod)
{
}

template<typename T>
std::enable_if_t<!std::is_pod<T>::value> f(T non_pod)
{
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!