是否有一个必须使用`is_detected_v`的典型用例?

时间:2017-03-28 09:01:05

标签: c++ standards language-design c++17 typetraits

以下摘自cppref

#include <experimental/type_traits>

template<class T>
using copy_assign_t = decltype(std::declval<T&>() = std::declval<const T&>());

struct Meow { };

using namespace std::experimental;

int main()
{
    static_assert(is_detected_v<copy_assign_t, Meow>,
        "Meow should be copy assignable!"); // version 1

    static_assert(is_copy_assignable_v<Meow>,
        "Meow should be copy assignable!"); // version 2
}

version 1version 2之间有什么区别吗?

是否有必须使用is_detected_v的典型用例?

2 个答案:

答案 0 :(得分:3)

std::is_detected可用作std::is_copy_assignable的构建基块。如果要检查复制可分配性,则应使用std::is_copy_assignable。如果您需要检查是否存在自定义操作/成员函数,std::is_detected为您提供了一种简单的方法。

template<class T>
using foo_detector = decltype(std::declval<T&>().foo());

static_assert(!is_detected_v<foo_detector, Meow>, "Meow shouldn't have `.foo()`!");

一个现实的示例用例是不同API的统一:

template<class T>
using clean_detector = decltype(std::declval<T&>().clean());

template<class T>
using clear_detector = decltype(std::declval<T&>().clear());

template <typename T>
auto clear(const T& x) -> std::enable_if_t<is_detected_v<has_clean, T>>
{
    x.clean();
}

template <typename T>
auto clear(const T& x) -> std::enable_if_t<is_detected_v<has_clear, T>>
{
    x.clear();
}

用法示例:

struct Foo { void clean(); };
struct Bar { void clear(); };

int main()
{
    Foo f; Bar b;
    clear(f);
    clear(b);
}

答案 1 :(得分:0)

检测到是否可以确定替换是否会导致失败。

这使您可以编写表达SFINAE支票的特征(临时与否)。

这些特征可以传递,用作标签和倒置。

所以我可以轻松地用它来写can_foo。然后我可以有两个重载,一个是can_foo另一个,如果是!can_foo

对于传统的SFINAE,如果can_foo很容易,写一个有效的重载;但是!can_foo很难。

如果计算,我们也可以标记调度或将其用于constexpr。

auto distance( Iterator A, Sentinal B ){
  if constexpr (can_subtract_v<Sentinal&, Iterator&>){
    return B-A;
  } else {
    // count manually
  }
}