首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++11 std等价于Boost has_dereference

C++11 std等价于Boost has_dereference
EN

Stack Overflow用户
提问于 2016-04-12 21:01:26
回答 3查看 347关注 0票数 3

Boost的许多SFINAE助手已经出现在带有C++11的std库中,但是has_dereference似乎没有。除了这个特性之外,我还设法从包中消除了一个Boost依赖项,并且我想完全消除它,那么如何最好地使用C++11 std特性来获得相同的效果呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-04-12 21:58:42

检查类是否具有没有外部依赖关系的函数的最简单方法通常是使用void_t成语。

代码语言:javascript
复制
// Define this once in your project somewhere accessible
template <class ... T>
using void_t = void;

然后,诀窍总是一样的;您定义了一个从std::false_type继承的类模板。

代码语言:javascript
复制
template <class T, class = void>
struct has_dereference : std::false_type {};

这是“回退”类模板。现在,我们将定义一个只有当类型具有我们想要的属性时才能工作的专门化:

代码语言:javascript
复制
template <class T>
struct has_dereference<T, void_t<decltype(*std::declval<T>())>> : std::true_type {};

要使用,只需:

代码语言:javascript
复制
bool x = has_dereference<int*>::value;
bool y = has_dereference<int>::value;

等。

我要补充的是,从技术上讲,operator*实际上是一个函数族;操作人员既可以是CV合格的,也可以是价值类别的合格的。无论何时对某一类型执行检测,实际上都是在这个家族中进行检测。我不会更详细地讨论它,因为在实践中很少会遇到它(operator*很少是值类别限定的,而且操作员几乎总是有一个const版本,而volatile很少出现),但是如果您看到了令人惊讶的东西,它是值得注意的。

这种技术是值得了解的,特别是如果您正在进行元编程而不依赖于Boost或Hana。您可以在这里阅读更多关于void_t的信息:工作

票数 6
EN

Stack Overflow用户

发布于 2016-04-13 02:09:46

这是一个整洁的小SFINAE特质写作助手。它使用std::void_t,如果缺少它,可以重新实现它。

代码语言:javascript
复制
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;

一旦你有了它,你的问题就很简单了。

代码语言:javascript
复制
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如下所示:

代码语言:javascript
复制
namespace details {
  template<class...>struct voider{using type=void;};
}
template<class...Ts>
using void_t=typename voider<Ts...>::type;

在一行中执行此操作会破坏一些较旧的编译器,而2行版本也很容易。

票数 4
EN

Stack Overflow用户

发布于 2016-07-13 02:43:20

Yakk的修改版本:

代码语言:javascript
复制
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...>>;

演示

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36583961

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档