首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >需要澄清SFINAE中的Lambdas、auto和decltype

需要澄清SFINAE中的Lambdas、auto和decltype
EN

Stack Overflow用户
提问于 2017-03-10 17:25:23
回答 1查看 117关注 0票数 0

我一直试图通过阅读下面的文章Link来学习SFINAE技巧,但在理解其中的某些部分时遇到了困难。

完整代码:Link

我主要对这几行代码感到困惑。

代码语言:javascript
复制
// Check if a type has a serialize method.
auto hasSerialize = is_valid([](auto&& x) 
    -> decltype(x.serialize()) { });

template <class T> auto serialize(T& obj) 
    -> typename std::enable_if<decltype(hasSerialize(obj))::value, std::string>::type
{
    return obj.serialize();
}

template <class T> auto serialize(T& obj) 
    -> typename std::enable_if<!decltype(hasSerialize(obj))::value, std::string>::type
{
    return to_string(obj);
}

特别是在hasSerialize行中,它用于带参数的decltype。有人能告诉我这里发生了什么吗?hasSerialize是一种方法吗?hasSerialize右边的表达式(λ)实际上是什么?评估中的执行顺序是什么?在hasSeriaize中,auto的值是什么?

请帮助我理解这一点,因为我已经挣扎了一周,但仍然无法理解它。如果有人能给出一个实际的例子,我将不胜感激。

谢谢

EN

回答 1

Stack Overflow用户

发布于 2017-03-10 17:37:15

首先,这段代码使用了boost::hana::is_valid --确保阅读它的文档并理解它在做什么。

是hasSerialize是一种方法吗?

不是,它是一个用lambda表达式初始化的变量。它是一个closure

hasSerialize右边的表达式(

)实际上是什么?

以下代码..。

代码语言:javascript
复制
auto hasSerialize = is_valid([](auto&& x) -> decltype(x.serialize()) { });

...will创建一个函数对象,当使用对象调用时,如果y.serialize()是有效表达式,则y将返回std::true_type,否则返回std::false_type。示例:

代码语言:javascript
复制
struct Foo { };
struct Bar { void serialize() { } };

static_assert(!hasSerialize(std::declval<Foo>()));
static_assert(hasSerialize(std::declval<Bar>()));

下面是is_valid的一个简单的可能实现

代码语言:javascript
复制
template <typename TF>
struct validity_checker
{
    template <typename... Ts>
    constexpr auto operator()(Ts... ts)
    {
        return std::is_callable<
            TF(typename decltype(ts)::type...)
        >{};
    }
};

template <typename TF>
constexpr auto is_valid(TF)
{
    return validity_checker<TF>{};
}

它简单地使用std::is_callable来查看是否可以使用一些特定的参数来调用带有尾随decltype的通用lambda。如果尾随的decltype 中的表达式对于某些特定的参数类型无效,则是不可调用的。

可以使用void_t以SFINAE友好的方式实现is_callable,如下所示

代码语言:javascript
复制
template <typename...>
using void_t = void;

template <typename, typename = void>
struct is_callable : std::false_type { };

template <typename TF, class... Ts>
struct is_callable<TF(Ts...),
    void_t<decltype(std::declval<TF>()(std::declval<Ts>()...))>>
    : std::true_type { };
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42714716

复制
相关文章

相似问题

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