4

So say that I want to make some constexpr functors, I though I could do this using bind. Is there something I'm missing? Why can't bind return a constexpr?

Given:

struct foo {
    int b() const { return _b; }
    int a() const { return _a; }
    int r() const { return _r; }
    const int _b;
    const int _a;
    const int _r;
};

I want to:

constexpr auto sumB = bind(plus<int>(), placeholders::_1, bind(&foo::b, placeholders::_2));
constexpr auto sumA = bind(plus<int>(), placeholders::_1, bind(&foo::a, placeholders::_2));
constexpr auto sumR = bind(plus<int>(), placeholders::_1, bind(&foo::r, placeholders::_2));

Is there something I could do to make this work?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288

2 Answers2

5

There is no technical obstacle to making bind constexpr; for example, the Sprout C++ Libraries have a constexpr-enabled bind.

However, implementations are not permitted to add constexpr to function signatures where it is not specified in the Standard, and there has not yet been any proposal to add constexpr to bind that I am aware of (Which parts of the C++14 Standard Library could be and which parts will be made constexpr?). It is fairly unlikely that one would be forthcoming, since bind is mostly superseded by lambda expressions, which as of C++17 are automatically constexpr:

constexpr auto sumB = [](int x, foo const& y) { return x + y.b(); };
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • This is great, as it answers my deeper question of why aren't `bind` results `constexpr` when they cannot do captures like lambdas therefor should be fully definable at compile-time. – Jonathan Mee Jul 28 '17 at 15:09
3

Well, we don't know what std::bind returns. It could probably be made to work but there is nothing mandated to make it work (nothing is defined as constexpr in std::bind's specification).

On thing you can do though, if you have access to C++17, is to use a lambda. In C++17 the operator() of the lambda will be marked constexpr by default allowing you to do something like

constexpr auto sumB = [](auto val, auto obj) { return val + obj.b(); };
constexpr auto sumA = [](auto val, auto obj) { return val + obj.a(); };
constexpr auto sumR = [](auto val, auto obj) { return val + obj.r(); };

Live Example

NathanOliver
  • 171,901
  • 28
  • 288
  • 402