C++17 新特性—— if constexpr

看代码说话

template <typename Iterator>
auto distance(Iterator begin, Iterator end) {
  using Traits = std::iterator_traits<Iterator>;
  if constexpr (std::is_base_of_v<std::random_access_iterator_tag, typename Traits::iterator_category>) {
    return end - begin;
  } else {
    auto result = typename Traits::difference_type();
    for (auto it = begin; it != end; ++it) {
      ++result;
    }
    return result;
  }
}

上面的代码用来判断两个iterator之间的距离。主要逻辑是判断iterator是否是可随机访问的iterator然后作分支处理,可以随机访问的迭代器直接把iterator相减。
constexpr if语句中,条件的值必须是可按语境转换到 bool 类型的经转换常量表达式。若其值为 true,则舍弃 false分支语句(若存在),否则舍弃 true分支语句。有意思的一点是,被舍弃语句中的 return 语句不参与函数返回类型推导,也就是说两个分支语句中的return推倒出来的类型允许不一样。

如果没有C++17这种怎么写呢?就是比较麻烦。
一可以加一个参数,但是每个tag写一个

template <typename Iterator>
auto distance(Iterator begin, Iterator end, std::bidirectional_iterator_tag); // one for each tag type

或者用SFINAE写两个

template <typename Iterator>
auto distance(Iterator begin, Iterator end, 
              typename std::enable_if_t<std::is_base_of_v<一大坨>>* = nullptr);

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.