简体   繁体   English

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

[英]Alternatives for std::enable_if and explicit overloading for template template parameters

Consider the following setup: 请考虑以下设置:

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
}

In other words - I'm creating a type that represents a graph. 换句话说-我正在创建代表图形的类型。 Nodes can be normal, or virtual, const and non-const. 节点可以是普通的,也可以是虚拟的,const和非const。 A Graph can contain a single node, or a node and a branch of graphs. 图可以包含一个节点,也可以包含图的一个节点和一个分支。

When I create a function f I want it to be const-neutral (do the same stuff on a const and non-const version of a node in a graph, but different on branched and unbranched graphs). 当我创建一个函数f我希望它是const中立的(在图中节点的const版本和非const版本上执行相同的操作,但在分支图和非分支图上执行不同的操作)。 Do I have to: 我一定要吗:

  1. Duplicate the code? 复制代码?
  2. Use std::enable_if hack? 使用std::enable_if骇客?

    1. Duplication of code duplicates bugs, so it is not optimal. 代码重复会复制错误,因此不是最佳选择。
    2. std::enable_if produces bad error messages in my case. 在我的情况下,std :: enable_if产生错误消息。

Is there a smarter solution to the problem that will make f accept const and non-const nodes? 有没有更聪明的解决方案来使f接受const和non-const节点?

Instead of using a template template parameter and have a gazillion overloads, just use a type template parameter: 不用使用模板模板参数并且具有大量的超载,只需使用类型模板参数即可:

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

T will be deduced to be Node<Foo> , vNode<Foo> or const Node<Foo> etc. as appropriate. T将推导TNode<Foo>vNode<Foo>const Node<Foo>等。 If Node vs vNode matters, you can always extract the type of the node with a simple trait class. 如果Node vs vNode重要,则始终可以使用简单的特征类提取节点的类型。 Similarly, you can use static_assert together with a trait class to ensure that T is a specialization of Node or vNode . 同样,可以将static_assert与trait类一起使用,以确保TNodevNode

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM