相当于Boost has_dereference的C++11 std
C++11 std equivalent of Boost has_dereference
Boost的许多SFINAE助手已经出现在C++11的std库中,但has_dereference
似乎没有。除了这个功能,我已经设法从我的包中消除了Boost依赖,我想完全消除它,那么如何最好地使用C++11 std功能来获得同样的效果呢?
检查类是否具有没有外部依赖项的函数的最简单方法通常是使用void_t
习惯用法。
// Define this once in your project somewhere accessible
template <class ... T>
using void_t = void;
那么诀窍总是一样的;定义一个从std::false_type
:继承的类模板
template <class T, class = void>
struct has_dereference : std::false_type {};
这是"回退"类模板。现在,我们将定义一个专门化,只有当类型具有我们想要的属性时才有效:
template <class T>
struct has_dereference<T, void_t<decltype(*std::declval<T>())>> : std::true_type {};
要使用,只需执行:
bool x = has_dereference<int*>::value;
bool y = has_dereference<int>::value;
等等。
我要补充的是,从技术上讲,operator*
实际上是一个函数族;操作员既可以是CV合格的,也可以是值类别合格的。无论何时对类型执行检测,实际上都是在该族中执行检测。我不会详细介绍它,因为它在实践中很少遇到(operator*
很少有值类别限定,运算符几乎总是有const版本,volatile很少出现),但值得注意的是,以防您看到令人惊讶的东西。
这项技术值得了解,尤其是当你在没有Boost或Hana等依赖关系的情况下进行元编程时。你可以在这里阅读更多关于void_t的信息:"void_t"是如何工作的。
这是一个简洁的小SFINAE特性写作助手。它使用std::void_t
,如果你没有它,你可以重新实现
namespace details {
template<template<class...>class Z, class v, class...Ts>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply=typename details::can_apply<Z, void, Ts...>::type;
一旦你有了这些,你的问题就很容易了。
template<class T>
using deref_result = decltype(*std::declval<T>());
template<class T>
using can_deref = can_apply<deref_result, T>;
这里的想法是隐藏std::void_t
机器。你写了一个特征来表达"某个计算的结果",从中我们可以得到"该计算有效吗"。
一个高度便携的void_t
看起来像:
namespace details {
template<class...>struct voider{using type=void;};
}
template<class...Ts>
using void_t=typename voider<Ts...>::type;
在一行中完成这项操作会破坏一些较旧的编译器,而两行版本也很容易。
Yakk的修改版本:
template <class...> struct pack {};
namespace detail {
template<template <class...> class Z, class Pack, class = void>
struct can_apply_impl : std::false_type {};
template<template<class...>class Z, class...Ts>
struct can_apply_impl<Z, pack<Ts...>, std::void_t<Z<Ts...>> > : std::true_type {};
}
template<template<class...>class Z, class...Ts>
using can_apply = detail::can_apply_impl<Z, pack<Ts...>>;
演示
- 为什么 c++11 std::lock 和 std::scoped_lock 至少需要 2 个参数?
- 为什么 c++11 std::normal_distribution 在从函数调用时返回相同的模式?
- C++11 std::regex后备选项
- 有什么理由C++ 11+ std::mutex 应该声明为全局变量,而不是作为函数参数传递到 std::thread 中
- 如何在<N>不发生内存泄漏的情况下同时(线程安全)填充 c++11 std::map<std::string,std::bitset*>?
- 如何在不接触函数本身的情况下暂停和恢复 C++11 std::thread 的功能
- C++11 std::列出拼接后的迭代器失效
- 我应该如何正确地播种C++11 std::d efault_random_engine
- How does c++11 std::ref work?
- 这是 clang c++11 std::regex_match 的功能还是错误?
- C 11 std :: This_thread :: Sleep_until()用GCC 4.8.5编译时挂起
- 如何使用C 11 STD ::线程实现类似Qthread的类
- 将 boost::thread 与 C++11 std::mutex 混合使用是否安全?
- C++11:std::locale::empty() 甚至是一个东西
- C++11 std::unique_ptr deleter
- C 11 std ::在不同的STL实现中使用哪些算法
- 如何使用C++11 std::thread设置堆叠大小
- 如果向量是特定的长度,则使用C++11 std::enable_if来启用成员函数
- 如何制作一个c++11 std::unordereded_set的std::weak_ptr
- C++ Visual C++ 2013 中的 11 std::enable_if 重载