1<!-- Copyright 2018 Paul Fultz II 2 Distributed under the Boost Software License, Version 1.0. 3 (http://www.boost.org/LICENSE_1_0.txt) 4--> 5 6FAQ 7=== 8 9#### Q: Why is `const` required for the call operator on function objects? 10 11Mutable function objects are not prohibited, they just need to be explicit by 12using the adaptor [`mutable_`](/include/boost/hof/mutable). The main reason for this, is that it can lead to 13many suprising behaviours. Many times function objects are copied by value 14everywhere. For example, 15 16```cpp 17struct counter 18{ 19 int i; 20 counter() : i(0) 21 {} 22 23 template<class... Ts> 24 int operator()(Ts&&...) 25 { 26 return i++; 27 } 28}; 29 30 31counter c{}; 32proj(mutable_(c))(1,1); 33// Prints 0, not 2 34std::cout << c.i << std::endl; 35``` 36 37The example won't ever yield the expected value, because the function mutates 38a copy of the objects. Instead, `std::ref` should be used: 39 40```cpp 41counter c{}; 42proj(std::ref(c))(1,1); 43// Prints 2 44std::cout << c.i << std::endl; 45``` 46 47Which will print the expected value. 48 49Another reason why `const` is required is because of supporting `constexpr` on 50C++11 compilers. In C++11, `constexpr` implies `const`, so it would be 51impossible to provide a non-const overload for functions that is `constexpr`. 52Instead, `constexpr` would have to be made explicit. Considering the pitfalls 53of mutable function objects, it would be better to make mutability explicit 54rather than `constexpr`. 55 56#### Q: Is the reinterpret cast in BOOST_HOF_STATIC_LAMBDA undefined behaviour? 57 58Not really, since the objects are empty, there is no data access. There is a 59static assert to guard against this restriction. 60 61Now there could be an insane implementation where this doesn't work(perhaps 62the lambdas are not empty for some strange reason), which the library would 63have to apply a different technique to make it work. However, this is quite 64unlikely considering that C++ will probably get constexpr lambdas and inline 65variables in the future. 66 67Alternatively, the factory pattern can be used instead of 68[`BOOST_HOF_STATIC_LAMBDA_FUNCTION`](BOOST_HOF_STATIC_LAMBDA_FUNCTION), which doesn't require an reinterpret cast: 69 70```cpp 71struct sum_factory 72{ 73 auto operator*() const 74 { 75 return [](auto x, auto y) 76 { 77 return x + y; 78 }; 79 } 80} 81 82BOOST_HOF_STATIC_FUNCTION(sum) = boost::hof::indirect(sum_factory{}); 83``` 84