Detecting if the called object is binary (including generic restricted lambdas)

I am trying to determine if the called object is binary (i.e. if its operator() takes two arguments). I want to perform this check on lambdas, including generic lambdas and limited generic lambdas (e.g. returning the return type std::enable_if_t ).


NOTE. this is not a duplicate of arty of the generic lambda . I just need to check if the common lambda is binary, and I can already do this for unlimited common lambdas or common lambdas that do not use arguments in their body.


My current approach is to apply one of the methods described in Kris Jusiak Boost.DI C ++ Now 2015 talk : any_type , This is basically a class that can be implicitly converted to any other class.

 struct any_type { template <typename T> constexpr operator T() const noexcept { return {}; } }; 

After defining any_type I use the discovery identifier to check if a particular called object can be called with two arguments:

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

This approach works well for both non-generic and generic 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)>{}); 

... but terribly fails when accessing an argument with an interface that is not supported by any_type or when the lambda constraint is limited:

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

error: static statement failed

 auto binary_generic_body = [](auto, auto x){ x.something(); }; // Compilation error! static_assert(is_binary_callable<decltype(binary_generic_constrained)>{}); 

error: "struct any_type" does not have a name with the name "something"

The full code is available here (by wandbox) .


Assuming I'm on the right track with any_type , is there a way to ignore the returned lambda type and lambda body? More details:

  • Is it possible to check if a generic restricted lambda is binary?

  • Is it possible to check if a universal lambda that is trying to access a specific member of its arguments is binary?

Otherwise, is there any other approach that could work here?

+5
source share

Source: https://habr.com/ru/post/1258472/


All Articles