std :: enable_if的替代方法和模板模板参数的显式重载

时间:2014-09-11 06:30:43

标签: c++ templates c++11 template-meta-programming overload-resolution

考虑以下设置:

template< typename Held >
class Node{
  //...
};

template< typename Held >
class vNode{
  //...
};

template <typename... Graphs>
class Branch{
  //...
};

template <typename...> class Graph; // undefined

template< 
  typename    node_t
> class Graph< node_t >{  //specialization for an ending node
  //...
};

template< 
  typename    node_t,
  typename... Graphs
> class Graph< node_t, Branch< Graphs...> >{  //specialization for a mid-graph node
  //...
};

template<
  template <typename> class node_t,
  typename Held
> void f( Graph< Node<Held> > ) {
  //stuff A on a node
}

template<
  template <typename> class node_t,
  typename Held
> void f( Graph< const Node<Held> > ) {
  //stuff A on a const node
}

template<
  template <typename> class node_t,
  typename Held
> void f( Graph< vNode<Held> > ) {
  //stuff B on a virtual node
}

template<
  template <typename> class node_t,
  typename Held
> void f( Graph< const vNode<Held> > ) {
   //stuff B on a virtual const node
}

template<
  template <typename> class node_t,
  typename Held,
  typename... Graphs
> void f( Graph< Node<Held>, Branch<Graphs...>> ) {
  //stuff C on a node with a branch
}

template<
  template <typename> class node_t,
  typename Held,
  typename... Graphs
> void f( Graph< const Node<Held>, Branch<Graphs...> > ) {
  //stuff C on a const node with a branch
}

template<
  template <typename> class node_t,
  typename Held,
  typename... Graphs
> void f( Graph< vNode<Held>, Branch<Graphs...> > ) {
  //stuff D on a virtual node with a branch
}

template<
  template <typename> class node_t,
  typename Held,
  typename... Graphs
> void f( Graph< const vNode<Held>, Branch<Graphs...> > ) {
   //stuff D on a virtual const node with a branch
}

换句话说 - 我正在创建一个代表图表的类型。节点可以是正常的,也可以是虚拟的,常量的和非常量的。图表可以包含单个节点,也可以包含节点和图形分支。

当我创建一个函数f时,我希望它是const-neutral(在图中的节点的const和非const版本上执行相同的操作,但在分支和非分支图上不同)。我必须:

  1. 复制代码?
  2. 使用std::enable_if hack?

    1. 重复代码会复制错误,因此不是最佳选择。
    2. std :: enable_if在我的情况下会产生错误的错误消息。
  3. 是否有一个更智能的解决方案可以使f接受const和非const节点?

1 个答案:

答案 0 :(得分:1)

只需使用类型模板参数,而不是使用模板模板参数并进行大量重载:

template<class T> void f( Graph<T> ) { /*...*/ }

T将视情况推断为Node<Foo>vNode<Foo>const Node<Foo>等。如果Node vs vNode很重要,您始终可以使用简单的特征类提取节点的类型。同样,您可以将static_assert与特质类一起使用,以确保TNodevNode的专业化。