我有一个定义为:
的类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
是可添加和非负类型才能正确实现。因此,如果enable_if
是无符号整数类型,如何正确使用E
构造才能启用此函数?
我目前看到两种并发症,我对接近感到不舒服:
E
。E
本身不用作类型,但在其他类型模板中使用。因为我对enable_if
构造相对较新,所以我会对这个问题的一些指导感到更自在,因为这是一个相对不重要的案例。
答案 0 :(得分:1)
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");
答案 1 :(得分:1)
如果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 F ailure I s N ot A n E rror)是有意义的,否则你正在做一些我们可以调用的东西 S ubstitution F ailure 我 s A lways A n E rror。在这些情况下,static_assert
更合适:
static_assert(std::is_integral<E>::value and std::is_unsigned<E>::value, "!");
将它作为功能的第一行。带有静态断言的错误消息通常也更加用户友好。
答案 2 :(得分:1)
这实际上并不是你想要做的。
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中编写代码。