需要在Sfinae中澄清Lambdas,Auto和SectType

Need clarification about Lambdas, auto and decltype in SFINAE

本文关键字:Lambdas Auto SectType Sfinae      更新时间:2023-10-16

我一直在尝试通过阅读以下文章链接来了解Sfinae技巧,但在理解其中的某些部分方面遇到了麻烦。

完整代码:链接

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

// 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 Line中,并且在宣传中使用了它。谁能告诉我这里发生了什么?Hasserialize是一种方法吗?Hasserialize右侧的表达式(Lambda)是什么?评估的执行顺序是什么?自动在哈西里化中评估什么?

请帮助我理解这一点,因为我为此苦苦挣扎了一个星期,但仍然无法围绕它。如果有人能为此提供一个实践的例子。

谢谢

首先,此代码使用boost::hana::is_valid-确保读取其文档并了解其在做什么。


Hasserialize是一种方法吗?

no,它是用lambda表达式初始初始化的变量。这是一个封闭。


Hasserialize右侧的表达式(Lambda)是什么?

以下代码...

auto hasSerialize = is_valid([](auto&& x) -> decltype(x.serialize()) { });

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

struct Foo { };
struct Bar { void serialize() { } };
static_assert(!hasSerialize(std::declval<Foo>()));
static_assert(hasSerialize(std::declval<Bar>()));

这是is_valid的简单实现:

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内的表达式对于某些特定参数类型无效,则lambda无法call.


is_callable可以使用void_t以下以下方式以Sfinae友好的方式实现:

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 { };