Skip to content

Commit

Permalink
Update quickstart documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
pfultz2 committed Apr 13, 2016
1 parent 0ef5ecd commit afce026
Showing 1 changed file with 26 additions and 6 deletions.
32 changes: 26 additions & 6 deletions doc/src/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Quick Start
Function Objects
----------------

The Fit library can work with all different types of functions in C++, including static functions, member functions, lambdas, and function objects. Function pointer(or member function pointers) can only refer to one function in an overload set of functions, and it requires explicit casting to select that overload:
The Fit library can work with all different types of functions in C++, including static functions, member functions, lambdas, and function objects. To refer to the function a function pointer(or member function pointer) can be used. However, a function pointer can only refer to one function in an overload set of functions, and it requires explicit casting to select that overload. For example, if we had a templated `sum` function, we would need an explicit cast to pass that function to the `std::accumulate`:

template<class T, class U>
auto sum(T x, U y)
Expand All @@ -17,7 +17,7 @@ The Fit library can work with all different types of functions in C++, including
int i = sum_int(1, 2);
// Or pass to an algorithm
std::vector<int> v = { 1, 2, 3 };
int total = std::accumulate(v.begin(), v.end(), 0, sump);
int total = std::accumulate(v.begin(), v.end(), 0, sum_int);


Instead, a function object allows the ability to encapsulate an entire overload set into one object. This can be done by defining a class that overrides the call operator like this:
Expand All @@ -43,16 +43,36 @@ There are few things to note about this. First, the call operator member functio

Because the function is templated, it can be called on any type that has the plus `+` operator, not just integers. Futhermore, the `sum` variable can be used to refer to the entire overload set.

Now, this is useful for local functions. However, many times we want to write functions and make them available for others to use. The Fit library provides [`FIT_STATIC_FUNCTION`](function.md) to declare the function object at global or namespace scope:
Lifting functions
-----------------

Another alternative to defining a function object, is to lift the templated function using [`FIT_LIFT`](lift.md). This will turn the entire overload set into one object like a function object:

template<class T, class U>
auto sum(T x, U y)
{
return x + y;
}

// Pass sum to an algorithm
std::vector<int> v = { 1, 2, 3 };
int total = std::accumulate(v.begin(), v.end(), 0, FIT_LIFT(sum));

However, due to limitations in C++14 this will not preserve `constexpr`. In those cases, its better to use a function object.

Declare functions
-----------------

Now, this is useful for local functions. However, many times we want to write functions and make them available for others to use. The Fit library provides [`FIT_STATIC_FUNCTION`](function.md) to declare the function object at the global or namespace scope:

FIT_STATIC_FUNCTION(sum) = sum_f();

The `FIT_STATIC_FUNCTION` declares a global variable following the best practices as outlined in [N4381](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html). This includes initializing the function object compile-time to avoid the [static initialization order fiasco](https://isocpp.org/wiki/faq/ctors#static-init-order) and the address of the function object is the same across translation units to avoid possible One-Definition-Rule(ODR) violations.
The [`FIT_STATIC_FUNCTION`](function.md) declares a global variable following the best practices as outlined in [N4381](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html). This includes compile-time initialization of the function object to avoid the [static initialization order fiasco](https://isocpp.org/wiki/faq/ctors#static-init-order) and an external address of the function object that is the same across translation units to avoid possible One-Definition-Rule(ODR) violations.

Adaptors
--------

Now we have defined the function as a function object, we can add new "enhancements" to the function. One enhancement is to write "exentsion" methods. The proposal [N4165](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4165.pdf) for Unified Call Syntax(UFCS) in C++17 would have allowed a function call of `x.f(y)` to become `f(x, y)`. Without UFCS in C++, we can instead use pipable function which would transform `x | f(y)` into `f(x, y)`. To make `sum_f` function pipable using the [`pipable`](pipable.md) adaptor, we can simply write :
Now we have defined the function as a function object, we can add new "enhancements" to the function. One enhancement is to write "extension" methods. The proposal [N4165](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4165.pdf) for Unified Call Syntax(UFCS) in C++17 would have allowed a function call of `x.f(y)` to become `f(x, y)`. Without UFCS in C++, we can instead use pipable function which would transform `x | f(y)` into `f(x, y)`. To make `sum_f` function pipable using the [`pipable`](pipable.md) adaptor, we can simply write:

FIT_STATIC_FUNCTION(sum) = pipable(sum_f());

Expand All @@ -64,7 +84,7 @@ Pipable function can be chained mutliple times just like the `.` operator:

auto four = 1 | sum(2) | sum(1);

Alternatively, instead of using the `|` operator, pipable functions can be chaned together using the [`flow`](flow.md) adaptor:
Alternatively, instead of using the `|` operator, pipable functions can be chained together using the [`flow`](flow.md) adaptor:

auto four = flow(sum(2), sum(1))(1);

Expand Down

0 comments on commit afce026

Please sign in to comment.