C++ 是否有一个典型的用例必须使用'Is\u detected\u v'?

C++ 是否有一个典型的用例必须使用'Is\u detected\u v'?,c++,standards,language-design,c++17,typetraits,C++,Standards,Language Design,C++17,Typetraits,以下摘录自: #包括 模板 使用copy_assign_t=decltype(std::declval()=std::declval()); 结构Meow{}; 使用名称空间std::实验; int main() { 静态断言(是否检测到), “喵喵应该是可复制分配的!”;//版本1 静态断言(是否为可分配副本), “喵喵应该是可复制分配的!”;//版本2 } 版本1和版本2之间有什么区别吗? 是否存在必须使用Is-detected\u v的典型用例?std::Is-detected可以用作s

以下摘录自:

#包括
模板
使用copy_assign_t=decltype(std::declval()=std::declval());
结构Meow{};
使用名称空间std::实验;
int main()
{
静态断言(是否检测到),
“喵喵应该是可复制分配的!”;//版本1
静态断言(是否为可分配副本),
“喵喵应该是可复制分配的!”;//版本2
}
版本1和版本2之间有什么区别吗?


是否存在必须使用
Is-detected\u v
的典型用例?
std::Is-detected
可以用作
std::Is-copy\u-assignable
的构建块。如果要检查副本可分配性,应使用
std::is\u copy\u 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()`!");

通过检测,您可以确定替换是否会导致失败

这允许您编写一个表示SFINAE检查的特征(即席或非即席)

这些特征可以被传递、用作标记和倒置

所以我可以用它轻松地写
canfoo
。然后我可以有两个重载,一个if
canfoo
另一个if
!can_foo

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

我们还可以标记dispatch或将其用于constexpr if计算

auto distance( Iterator A, Sentinal B ){
  if constexpr (can_subtract_v<Sentinal&, Iterator&>){
    return B-A;
  } else {
    // count manually
  }
}
自动距离(迭代器A、前导B){
if constexpr(可以减去v){
返回B-A;
}否则{
//人工计数
}
}

这方面的用例是SFINAE,而不是硬错误。如果您想要一个硬错误,更直接的解决方案是好的。
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);
}
auto distance( Iterator A, Sentinal B ){
  if constexpr (can_subtract_v<Sentinal&, Iterator&>){
    return B-A;
  } else {
    // count manually
  }
}