FAQ

Q: Why is const required for the call operator on function objects?

Mutable function objects are not prohibited, they just need to be explicit by using the adaptor mutable. The main reason for this, is that it can lead to many suprising behaviours. Many times function objects are copied by value everywhere. For example,

struct counter
{
    int i;
    counter() : i(0)
    {}

    template<class... Ts>
    int operator()(Ts&&...)
    {
        return i++;
    }
};


counter c{};
proj(mutable_(c))(1,1);
// Prints 0, not 2
std::cout << c.i << std::endl;

The example won’t ever yield the expected value, because the function mutates a copy of the objects. Instead, std::ref should be used:

counter c{};
proj(std::ref(c))(1,1);
// Prints 2
std::cout << c.i << std::endl;

Which will print the expected value.

Another reason why const is required is because of supporting constexpr on C++11 compilers. In C++11, constexpr implies const, so it would be impossible to provide a non-const overload for functions that is constexpr. Instead, constexpr would have to be made explicit. Considering the pitfalls of mutable function objects, it would be better to make mutability explicit rather than constexpr.

Q: Is the reinterpret cast in BOOST_HOF_STATIC_LAMBDA undefined behaviour?

Not really, since the objects are empty, there is no data access. There is a static assert to guard against this restriction.

Now there could be an insane implementation where this doesn’t work(perhaps the lambdas are not empty for some strange reason), which the library would have to apply a different technique to make it work. However, this is quite unlikely considering that C++ will probably get constexpr lambdas and inline variables in the future.

Alternatively, the factory pattern can be used instead of BOOST_HOF_STATIC_LAMBDA_FUNCTION, which doesn’t require an reinterpret cast:

struct sum_factory
{
    auto operator*() const
    {
        return [](auto x, auto y)
        {
            return x + y;
        };
    }
}

BOOST_HOF_STATIC_FUNCTION(sum) = boost::hof::indirect(sum_factory{});