检测可调用对象是否为二进制(包括通用约束lambda)

Vit*_*meo 5 c++ lambda c++14 detection-idiom c++17

我正在尝试检测可调用对象是否为二进制(即,它是否operator()采用两个参数).我想对lambdas执行此检查,包括泛型lambdas约束泛型lambda (例如,使用尾随std::enable_if_t返回类型).


注意:不是"普通lambda的arity"的副本.我只关心检查泛型lambda是否是二进制的,并且我已经可以为不受约束的泛型lambda不使用其体中的参数的泛型lambda做到这一点.


我目前的方法是应用Kris Jusiak的Boost.DI C++ Now 2015谈话中描述的技术之一:any_type.它基本上是一个可以隐式转换为任何其他类的类.

struct any_type
{
    template <typename T>
    constexpr operator T() const noexcept
    {
        return {};
    }
};
Run Code Online (Sandbox Code Playgroud)

在定义之后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>;
Run Code Online (Sandbox Code Playgroud)

这种方法适用于非泛型和通用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)>{});
Run Code Online (Sandbox Code Playgroud)

...但是当使用不受any_typelambda约束的接口或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)>{});
Run Code Online (Sandbox Code Playgroud)

错误:静态断言失败

auto binary_generic_body = [](auto, auto x){ x.something(); };

// Compilation error!
static_assert(is_binary_callable<decltype(binary_generic_constrained)>{});
Run Code Online (Sandbox Code Playgroud)

错误:'struct any_type'没有名为'something'的成员

完整的代码在这里可用(在wandbox上).


假设我在正确的轨道上any_type,有没有办法忽略lambda的返回类型和lambda的身体?更详细:

  • 是否可以检查通用约束lambda是否为二进制?

  • 是否有可能检查尝试访问其参数的特定成员的泛型lambda是否为二进制?

否则,还有其他方法可以在这里工作吗?