需要澄清SFINAE中的Lambdas,auto和decltype

时间:2017-03-10 09:25:23

标签: c++ templates lambda sfinae auto

我一直在尝试通过阅读以下文章Link来了解SFINAE技巧,但却难以理解它的某些部分。

完整代码:Link

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

// 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右侧的表达式(lambda)将实际评估为什么?评估中的执行顺序是什么?在hasSeriaize中自动计算的内容是什么?

请帮助我理解这一点,因为我在这个问题上挣扎了一个星期,但仍然可以解决这个问题。如果任何人能够提供一个实际的例子,我将不胜感激。

由于

1 个答案:

答案 0 :(得分:1)

首先,此代码使用boost::hana::is_valid - 请务必阅读其文档并了解它的作用。

  

hasSerialize是一种方法吗?

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

  

hasSerialize右侧的表达式(lambda)将实际评估为什么?

以下代码......

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

...将创建一个函数对象,当使用对象y调用时,如果std::true_type是有效表达式{{1},则返回y.serialize() }} 除此以外。例如:

std::false_type

这是struct Foo { }; struct Bar { void serialize() { } }; static_assert(!hasSerialize(std::declval<Foo>())); static_assert(hasSerialize(std::declval<Bar>())); 的简单可能实现:

is_valid

它只是使用std::is_callable来查看是否可以使用某些特定参数调用带有尾随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>{}; } 泛型lambda 如果尾部decltype内的表达式对某些特定参数类型无效,则lambda不可调用。

decltype可以使用is_callable以符合SFINAE的方式实施,如下所示:

void_t