我正在尝试检测可调用对象是否是二进制的(即,如果它operator()
有两个参数)。我想对 lambdas 执行此检查,包括泛型 lambdas和受约束的泛型 lambdas (例如,带有尾随std::enable_if_t
返回类型)。
注意:这不是"arity of a generic lambda"的副本。我只关心检查泛型 lambda 是否是二进制的,我已经可以为不受约束的泛型 lambda或不使用其 body 中的参数的泛型 lambda 做到这一点。
我目前的方法包括应用Kris Jusiak 的 Boost.DI C++Now 2015 演讲中描述的一种技术:any_type
. 它基本上是一个可以隐式转换为任何其他类的类。
struct any_type
{
template <typename T>
constexpr operator T() const noexcept
{
return {};
}
};
定义后any_type
,我使用检测习惯来检查是否可以使用两个参数调用特定的可调用对象:
template<class T>
using is_binary_callable_impl = decltype(std::declval<T>()(any_type{}, any_type{}));
template <typename T>
using is_binary_callable = std::experimental::is_detected<is_binary_callable_impl, T>;
这种方法适用于非泛型和泛型 lambda...
auto unary_nongeneric = [](int){};
auto unary_generic = [](auto){};
auto binary_nongeneric = [](int, float){};
auto binary_generic = [](auto, auto){};
static_assert(!is_binary_callable<decltype(unary_nongeneric)>{});
static_assert(!is_binary_callable<decltype(unary_generic)>{});
static_assert(is_binary_callable<decltype(binary_nongeneric)>{});
static_assert(is_binary_callable<decltype(binary_generic)>{});
...但是当使用不受 lambda 支持的接口any_type
或当 lambda 受到约束时访问参数时,会严重失败:
auto binary_generic_constrained = [](auto, auto x)
-> std::enable_if_t<std::is_arithmetic<std::decay_t<decltype(x)>>{}> {};
// Fails!
static_assert(is_binary_callable<decltype(binary_generic_constrained)>{});
错误:静态断言失败
auto binary_generic_body = [](auto, auto x){ x.something(); };
// Compilation error!
static_assert(is_binary_callable<decltype(binary_generic_constrained)>{});
错误:“struct any_type”没有名为“something”的成员
假设我在正确的轨道上any_type
,有没有办法忽略 lambda 的返回类型和 lambda 的主体?更详细地说:
是否可以检查通用约束 lambda 是否是二进制的?
是否可以检查尝试访问其参数的特定成员的通用 lambda 是否是二进制的?
否则,还有其他方法可以在这里工作吗?