[英]How do I correctly use enable_if in this specific function declaration?
我有一个类定义为:
template <typename V, typename E>
class AdjacencyList;
其中V和E分别是顶点和边缘值的类型。
我目前正在尝试在AdjacencyList
定义以下成员函数:
std::map< std::shared_ptr< Vertex<V, E> >, E > dijkstra(
const std::shared_ptr< Vertex<V, E> > &start_vertex) const;
对于那些熟悉Dijkstra算法的人来说,只有在E
是可添加和非负类型的情况下才能正确实现。 因此,如果E
是无符号整数类型,如何正确使用enable_if
结构才能启用此函数?
我目前看到两个并发症,我对接近感到不舒服:
E
。 E
本身不用作类型,但在其他类型模板中使用。 因为我对enable_if
构造相对较新,所以我会对这个问题的一些指导感到更舒服,因为这是一个相对不重要的案例。
如果要编写具有调整类型要求的多个重载,则enable_if
很有用。 在您的情况下,您没有任何重载,只想强制执行某些类型限制。 因此,您可以使用static_assert
检查它们并为用户提供有意义的诊断消息,而不是通常的模板实例化故障。 像这样的东西:
<type_traits>
<utility>
...
static_assert(::std::is_unsigned< E >::value, "edge value type must be unsigned integral type");
static_assert(::std::is_same< E, decltype(::std::declval< E >() + ::std::declval< E >()) >, "edge value type must be addable");
如果E是无符号整数类型,则仅启用此函数
我按原样收到您的评论/请求,并直接使用<type_traits>
提供的工具。
如果你想使用std::enable_if
,可能以下几乎可以为你工作:
std::enable_if_t<std::is_integral<E>::value and std::is_unsigned<E>::value, std::map< std::shared_ptr< Vertex<V, E> >, E >> dijkstra( const std::shared_ptr< Vertex<V, E> > &start_vertex) const;
无论如何,SFINAE(S ubstitution˚Failure 我 S N加时赛一否E RROR)是有道理的,当你有多个选项,否则你正在做的事情,我们可以称S ubstitution˚Failure I S 一 lways 一个 N个E RROR。 在这些情况下, static_assert
更合适:
static_assert(std::is_integral<E>::value and std::is_unsigned<E>::value, "!");
把它作为你的功能的第一行。 具有静态断言的错误消息通常也更加用户友好。
这实际上并不是你想要做的。
std::enable_if
是导致模板的替换失败。 您希望替换失败的原因是因为它不是失败,您可以选择不同的重载。 但是,这里没有意义,因为你并没有尝试选择不同的重载,而只是试图让它失败。
所以,你会做这样的事情:
std::map< std::shared_ptr< Vertex<V, E> >, E > dijkstra(
const std::shared_ptr< Vertex<V, E> > &start_vertex) const {
static_assert(
std::is_unsigned<E>::value,
"E must be unsigned.");
}
如果您尝试使用错误类型的参数调用此函数,则会得到一个很好的编译时错误,告诉您E必须是可添加的且非负的。 如果您使用了enable_if
,则会收到一个错误,即没有任何重载是有效的,这是一个信息量较小的错误。
不过,这可能是一个糟糕的设计。 通常,如果遇到负值,则只会抛出异常。 选择强制输入是正数也是不完整的,因为如果遇到溢出,算法也会失败。
(如果你真的想做enable_if
即使这是个坏主意,你也可以..)
std::enable_if<std::is_unsigned<E>,
std::map<std::shared_ptr<Vertex<V, E>>, E>::type dijkstra...
C ++是这种类型的编程的错误语言 ,并且在它以这种方式工作之前锤击C ++将导致一些非常古怪的C ++代码。 听起来你真的想在Agda中编写代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.