是否有必须使用 `is_detected_v` 的典型用例?
Is there a typical use case that must use `is_detected_v`?
以下摘自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 1
和version 2
有区别吗?
是否有必须使用is_detected_v
的典型用例?
std::is_detected
可以用作 std::is_copy_assignable
的积木。如果你想检查可复制性,你应该使用 std::is_copy_assignable
。如果您需要检查自定义 operation/member 函数是否存在,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);
}
检测到可让您确定替换是否会导致失败。
这让您可以编写一个特征(临时的或非临时的)来表达 SFINAE 检查。
此类特征可以传递、用作标签和反转。
所以我可以用它轻松地写can_foo
。然后我可以有两个重载,一个如果 can_foo
另一个如果 !can_foo
.
使用传统的 SFINAE,编写一个在 can_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
}
}
以下摘自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 1
和version 2
有区别吗?
是否有必须使用is_detected_v
的典型用例?
std::is_detected
可以用作 std::is_copy_assignable
的积木。如果你想检查可复制性,你应该使用 std::is_copy_assignable
。如果您需要检查自定义 operation/member 函数是否存在,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);
}
检测到可让您确定替换是否会导致失败。
这让您可以编写一个特征(临时的或非临时的)来表达 SFINAE 检查。
此类特征可以传递、用作标签和反转。
所以我可以用它轻松地写can_foo
。然后我可以有两个重载,一个如果 can_foo
另一个如果 !can_foo
.
使用传统的 SFINAE,编写一个在 can_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
}
}