• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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