C++ Guru Question – followup

(following on from C++ Guru Question)

There are a few reasons why the code before didn’t work: mainly

a) C++ template argument deduction works one-way with a list of candidates, it’s not H-M type inference.
b) A C++ lambda is a thing with some internal type, not a std::function (although it can be assigned to one, that doesn’t matter for template type deduction).

Anyway, a reasonable solution to this problem is to simplify the template argument matching to the function type, and use a simple function_traits template to take apart the function argument and return types.

template <typename T>
struct function_traits
  : public function_traits<decltype(&T::operator())>
template <typename R, typename A>
struct function_traits<R(A)>
  typedef R returnType;
  typedef A argType;
template <typename C, typename R, typename A>
struct function_traits<R(C::*)(A) const>
  : public function_traits<R(A)>
template <typename T>
struct Foo
  T m_t;
template <typename F>
typename function_traits<F>::returnType operator/=(
    Foo<typename function_traits<F>::argType> foo, const F& fn)
  return fn(foo.m_t);
void mystery()
  auto foo = Foo<int>{1};
  // this works...
  function<Foo<int>(int)> f1 = [] (int i) { return Foo<int>{i}; };
  auto bar1 = foo /= f1;
  // this does too!
  auto f2 = [] (int i) { return Foo<int>{i}; };
  auto bar2 = foo /= f2;

Leave a Reply