繁体   English   中英

如何在此特定函数声明中正确使用enable_if?

[英]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结构才能启用此函数?

我目前看到两个并发症,我对接近感到不舒服:

  1. 返回类型和参数都与E
  2. 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.

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