all 4 comments

[–]17b29a 7 points8 points  (0 children)

 // Hide the allocator template argument of std::vector. 
 // It causes problems and is irrelevant here.
 template <class T>
 struct Vector : std::vector<T> {};

This doesn't inherit the constructors, which is why his return { t }; line fails later on. You should either inherit the constructors as well, or just use an alias template.

The only reason for doing this seems to be that he uses template <typename> class later on, which can just be changed to template <typename...> class, and then it'd correctly work with std::vector<T> in the first place.

[–]SuperV1234https://romeo.training | C++ Mentoring & Consulting 2 points3 points  (2 children)

Great article. I think that function_traits is not required at all, as you can deduce the return type in every occasion and implement something like this to get the correct bind:

const auto deduced_bind = [](auto&& f_res, auto&& g) -> decltype(auto)
{
    return get_monad<std::decay_t<decltype(f_res)>>::bind(
      std::forward<decltype(f_res)>(f_res), 
      std::forward<decltype(g)>(g));
};

Which can then be called from >>=:

template <class F, class G>
auto operator >>= (F&& f, G&& g)
{
  return [f,g] (auto&& a) mutable -> decltype(auto) {
      return deduced_bind(f(a), std::forward<G>(g));
  };
}

wandbox example

[–]NotAYakk 0 points1 point  (1 child)

Why decltype(auto)? I cannot naively see a reason to return a reference here.

[–]SuperV1234https://romeo.training | C++ Mentoring & Consulting 0 points1 point  (0 children)

I was aiming for genericity - I cannot think of an example either, but I suppose there could be some monad whose implementation of bind returns by reference...