Dobiasd / FunctionalPlus

Functional Programming Library for C++. Write concise and readable C++ code.
http://www.editgym.com/fplus-api-search/
Boost Software License 1.0
2.07k stars 168 forks source link

Added noexcept variants to function traits #297

Closed LuSo58 closed 3 months ago

LuSo58 commented 3 months ago

When using function_traits with callable items that are noexcept, no specialization would match. Here is a simple reproduction case for this.

#include <iostream>
#include <functional>

#include "fplus/fplus.hpp"

template<typename F, typename T = typename fplus::utils::function_traits<F>::template arg<0>::type>
auto forward(F f) {
  return [f](auto x) {
    auto ret = f(x);
    return ret;
  };
}

class klass {
  public:
    int x;

    int normal() const {
      return x;
    }

    int noexc() const noexcept {
      return x;
    }
};

int half(int x) {
  return x / 2;
}

int half_noexc(int x) noexcept {
  return x / 2;
}

struct functor {
  int operator()(int x) {
    return x + 5;
  }
};

struct functor_noexc {
  int operator()(int x) noexcept {
    return x + 5;
  }
};

int main() {
  klass k = {42};
  std::cout << forward(std::mem_fn(&klass::normal))(k) << std::endl; // OK
  std::cout << forward(std::mem_fn(&klass::noexc))(k) << std::endl; // Will not compile
  std::cout << forward(half)(42) << std::endl; // OK
  std::cout << forward(half_noexc)(42) << std::endl; // Will not compile
  std::cout << forward(functor())(42) << std::endl; // OK
  std::cout << forward(functor_noexc())(42) << std::endl; // Will not compile
  auto lambda = [](int x) {
    return x + 10;
  };
  auto lambda_noexc = [](int x) noexcept {
    return x + 10;
  };
  std::cout << forward(lambda)(42) << std::endl; // OK
  std::cout << forward(lambda_noexc)(42) << std::endl; // Will not compile
}
Dobiasd commented 3 months ago

Oh, very good finding, thanks a lot! :heart_eyes:

(And since the source repo of the function traits seems to no longer be maintained, I guess it does not make sense to try to include it there.)

LuSo58 commented 3 months ago

I added macros to hide the noexcept specs from compilers, that don't seem to distinguish between the signatures. See the checks results. I don't know how to force rerun the checks, so I can't check if it works easily.

Dobiasd commented 3 months ago

Thanks!

Yeah, I need to approve such runs - probably to prevent people from using the CI to mine Bitcoins or similar. ;)


Edit: Just for later reference. It continues here: https://github.com/Dobiasd/FunctionalPlus/pull/298