C++ std::enable_if和模板参数的显式重载的备选方案
请考虑以下设置:C++ std::enable_if和模板参数的显式重载的备选方案,c++,templates,c++11,template-meta-programming,overload-resolution,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&l
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
}
template
类节点{
//...
};
模板
类vNode{
//...
};
模板
班支部{
//...
};
模板类图;//未定义
模板<
类型名称节点
>类图{//结束节点的专门化
//...
};
模板<
类型名节点,
类型名。。。图
>类图>{//中间图节点的专门化
//...
};
模板<
模板类节点,
保留的字体名
>void f(图){
//在节点上填充
}
模板<
模板类节点,
保留的字体名
>空f(图形<常量节点>){
//在常量节点上填充
}
模板<
模板类节点,
保留的字体名
>空f(图形){
//在虚拟节点上填充B
}
模板<
模板类节点,
保留的字体名
>空f(图){
//在虚拟常量节点上填充B
}
模板<
模板类节点,
字体名称保持不变,
类型名。。。图
>空f(图<节点,分支>){
//在带有分支的节点上填充C
}
模板<
模板类节点,
字体名称保持不变,
类型名。。。图
>void f(图<常量节点,分支>){
//在具有分支的常量节点上填充C
}
模板<
模板类节点,
字体名称保持不变,
类型名。。。图
>空f(图){
//在带有分支的虚拟节点上填充D
}
模板<
模板类节点,
字体名称保持不变,
类型名。。。图
>空f(图){
//在具有分支的虚拟常量节点上填充D
}
换句话说,我正在创建一个表示图形的类型。节点可以是普通节点,也可以是虚拟节点、常量节点和非常量节点。一个图可以包含单个节点,也可以包含一个节点和一个图分支
当我创建一个函数f
时,我希望它是常量中立的(在图中的一个节点的常量和非常量版本上执行相同的操作,但在分支图和非分支图上执行不同的操作)。我是否必须:
std::启用\u如果hack
代码的重复会复制错误,因此它不是最佳的
std::enable_如果在我的案例中生成错误消息
是否有一种更智能的解决方案可以使
f
接受常量和非常量节点?只需使用类型模板参数,而不是使用模板参数和大量重载:
template<class T> void f( Graph<T> ) { /*...*/ }
模板空f(图){/*…*/}
T
将被推断为Node
、vNode
或const Node
等。如果Node
vsvNode
很重要,则始终可以使用简单的trait类提取节点的类型。类似地,您可以将static\u assert
与trait类一起使用,以确保T
是Node
或vNode
的特化,为什么不简单地template void f(Graph)
并让T
得到适当的推导呢?您总是可以使用trait类轻松提取节点类型。为什么Graph
和Graph>代码>相同的模板
,如果它们有不同的实现、接口,并且使用方式不同?还是有相同的功能处理它们?例如,您可以编写一个工厂模板,根据它是否为终端返回不同的类型。@Yakk:原因有二:1。图
是从分支
派生的,分支是std::tuple
包装器。由于std::tuple
不是零大小,我认为空基优化不适用。2.有一些递归函数遍历图形
,在终端节点上终止它们需要函数重载。Graph
的重载与Graph
没有太大区别,后者产生的错误更短,意图更明确@TC:这是一个很好的主意,我支持它。谢谢你一如既往,这应该作为一个答案张贴。