Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;11标准升压等效值已取消参考_C++_C++11_Boost_Sfinae_Typetraits - Fatal编程技术网

C++ C++;11标准升压等效值已取消参考

C++ C++;11标准升压等效值已取消参考,c++,c++11,boost,sfinae,typetraits,C++,C++11,Boost,Sfinae,Typetraits,Boost的许多SFINAE助手已经用C++11出现在std库中,但是似乎没有。除了这个特性之外,我已经设法从我的包中消除了Boost依赖项,我想完全消除它,那么如何最好地使用C++11 std特性来获得相同的效果呢?检查类是否具有没有外部依赖项的函数的最简单方法通常是使用void\t习惯用法 // Define this once in your project somewhere accessible template <class ... T> using void_t = v

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

检查类是否具有没有外部依赖项的函数的最简单方法通常是使用
void\t
习惯用法

// Define this once in your project somewhere accessible
template <class ... T>
using void_t = void;
这是“回退”类模板。现在,我们将定义一个专门化,该专门化仅在类型具有我们想要的属性时有效:

template <class T>
struct has_dereference<T, void_t<decltype(*std::declval<T>())>> : std::true_type {};
模板
结构有_-dereference:std::true_-type{};
要使用,只需执行以下操作:

bool x = has_dereference<int*>::value;
bool y = has_dereference<int>::value;
boolx=has\u dereference::value;
bool y=has_dereference::value;
等等

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


这项技术值得了解,尤其是当您在进行元编程时,没有依赖项,如Boost或Hana。你可以在这里阅读更多关于void的信息:。

这是一个整洁的小SFINAE特质写作助手。它使用
std::void\u 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;

在一行中完成此操作会破坏一些较旧的编译器,两行版本也很简单。

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...>>;
模板结构包{};
名称空间详细信息{
模板
结构可以应用:std::false\u类型{};
模板
结构可以应用:std::true\u类型{};
}
模板
使用can\u apply=detail::can\u apply\u impl;

您不能只看一下实现吗?我不知道具体的许可证,但您可以将Boost实现复制粘贴到您的代码中。只能是标题,不能太长。@Nicol我想你没有?;-)它通过covert(和复杂外观)定义完成,如BOOST_TT_banbidden_IF,由内部has_prefix_operator.hpp头使用,然后再次取消定义。因此,进行逆向工程并不容易,而且肯定不仅仅是将Boost中的代码复制到基于std的代码中。不,我真的没有,显然我猜错了。:)有帮助吗?@BaummitAugen啊,看起来很有用。我明天就试试,谢谢!效果很好。非常感谢。啊,我打错了。我想已经修好了@雅克证实了这一点。这并不是一个新的答案,更多的是对雅克的评论,他有一个打字错误?@Barry it用我的答案解决了这个问题,与我的答案略有不同(或者会有)。结果是一个变体。相同的语义,不同的实现。
template<class T>
using deref_result = decltype(*std::declval<T>());

template<class T>
using can_deref = can_apply<deref_result, T>;
namespace details {
  template<class...>struct voider{using type=void;};
}
template<class...Ts>
using void_t=typename voider<Ts...>::type;
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...>>;