How to determine if a common lambda is incompatible in C ++ 14?

I have a problem with detecting when the instance of the generated lambda is well-formed but not compilable, and finding this puzzled me:

#include <functional>

class future
{
public:
  int get() & { return 5; }
};

// Gets the return type of F(A), returning a not_well_formed type if not well formed
template<class F, class A> struct get_return_type
{
  struct not_well_formed {};
  template<class _F, class _A> static not_well_formed test(...);
  template<class _F, class _A> static auto test(_F &&f) noexcept(noexcept(f(std::declval<_A>()))) -> decltype(f(std::declval<_A>()));
  using type = decltype(test<F, A>(std::declval<F>()));
  static constexpr bool is_noexcept = noexcept(test<F, A>(std::declval<F>()));
};

int main(void)
{
  auto foo=[](auto &&x) { return x.get(); };
  using type=get_return_type<decltype(foo), const future>::type;
  return 0;
}

This fails (on clang 3.7):

ned@kate:~$ clang++-3.7 -std=c++14 -o weird_generic_lambda_thing weird_generic_lambda_thing.cpp 
weird_generic_lambda_thing.cpp:21:34: error: member function 'get' not viable: 'this' argument has type 'const future', but
      function is not marked const
  auto foo=[](auto &&x) { return x.get(); };
                                 ^
weird_generic_lambda_thing.cpp:14:111: note: in instantiation of function template specialization 'main()::(anonymous
      class)::operator()<const future>' requested here
  ..._F, class _A> static auto test(_F &&f) noexcept(noexcept(f(std::declval<_A>()))) -> decltype(f(std::declval<_A>()));
                                                                                                  ^
weird_generic_lambda_thing.cpp:15:25: note: while substituting explicitly-specified template arguments into function
      template 'test'
  using type = decltype(test<F, A>(std::declval<F>()));
                        ^
weird_generic_lambda_thing.cpp:22:14: note: in instantiation of template class 'get_return_type<(lambda at
      weird_generic_lambda_thing.cpp:21:12), const future>' requested here
  using type=get_return_type<decltype(foo), const future>::type;
             ^
weird_generic_lambda_thing.cpp:6:7: note: 'get' declared here
  int get() & { return 5; }
      ^
1 error generated.

Perhaps you can blame my inexperience with Expression SFINAE here (thanks to Visual Studio!), But I am surprised: for sure, the decltype type that creates the test () return type cannot be replaced if it is f(std::declval<_A>())not formed correctly?

Obviously, the answer lies in the fact that it does not replace, but in a method other than SFINAE. Could this be fixed so that it correctly returns the not_well_formed type if the common lambda is incompatible with any arbitrary type of parameter?

+4
source share
1

. SFINAE . - , ( ).

SFINAE ->decltype(x.get()) SFINAE, enable_if_t void_t.

, , .

+7

All Articles