C++
section
C++
98std::function
C
-stylevoid qsort(void* pointer, size_t count, size_t size,
int (*comparator) (const void*, const void*));
int greater(const void* lhs, const void* rhs) {
const int* l = static_cast<const int*>(lhs);
const int* r = static_cast<const int*>(rhs);
return *r - *l;
}
// ...
std::qsort(numbers, 5, sizeof(int), &greater);
C++'98
does not allow defining functions inside functionsC++
'98 stylevoid sort(T begin, T end, C comparator);
operator <
template <typename T, typename P>
T partition(T begin, T end, P unary_predicate);
// partitions a range so that all X for which predicate(X) is true
// precede all Y for which predicate(Y) is false
template <typename T>
struct less_than_t
{
explicit less_than_t(T value)
: _value(value)
{}
bool operator()(T x) const {
return x < _value;
}
T _value;
};
template <typename T>
less_than_t<T> less_than(T x)
{
return less_than_t<T>(x);
}
std::partition(numbers, numbers + size, less_than(5));
struct
can be defined inside a function
struct
s can not be used for instantiating templates
g++
say soC++
11 styleAnonymous functions that can be defined inside functions and can access variables defined outside the anonymous functions.
[capture](parameters) -> return_type { function_body }
std::vector<int> v;
std::partition(v.begin(), v.end(), [](int x) {
return x % 2 == 0;
});
std::for_each(v.begin(), v.end(), [&](int x) {
std::cout << x << std::endl;
});
[]
- no variables are captured[x]
- x is captured by value[&x]
- x is captured by ref[&]
- any external variable is implicitly captured by ref[=]
- any external variable is implicitly captured by value[x, &y]
- x is captured by value, y - by referencethis
can be captured only by value and only inside methodsMost compilers generate a struct
with a special name and operator()
struct
auto dbl = [](auto x) { return x + x; };
std::vector<int> vi;
std::transform(vi.begin(), vi.end(), vi.begin(), dbl);
std::vector<std::string> vs;
std::transform(vs.begin(), vs.end(), vs.begin(), dbl);
std::vector<int> vi;
std::tranform(vi.begin(), vi.end(), vi.begin(),
[value = 42](auto x) {
return x + value;
});
auto ptr = std::make_unique<int>(42);
std::vector<int> vi;
std::tranform(vi.begin(), vi.end(), vi.begin(),
[ptr = std::move(ptr)](auto x) {
return x + *ptr;
});
std::vector<int> lengths;
std::vector<string> strings;
lengths.resize(strings.size());
std::transform(strings.begin(), strings.end(), lengths.begin(),
// ???
);
std::transform(strings.begin(), strings.end(), lengths.begin(),
std::string::length // ???
);
// No
C++
free functions
methods
free_function(a, 42);
object.method(42);
size_t get_length(const std::string& s) {
return s.length();
}
std::transform(strings.begin(), strings.end(), lengths.begin(),
get_length;
);
C++
98std::transform(strings.begin(), strings.end(), lengths.begin(),
std::mem_fun_ref(&std::string::length);
);
std::mem_fun
std::mem_fun_ref
works with a referencestd::bind1st
and std::bind2nd
Bind the first (second) argument of a function to a fixed value and return a function with one argument less.
DEPRECATED
std::vector<std::string> v;
std::transform(v.begin(), v.end(), v.begin(),
std::bind1st(std::plus<std::string>(), ";"));
// "x" -> ";x"
std::transform(v.begin(), v.end(), v.begin(),
std::bind2nd(std::plus<std::string>(), ";"));
// "x" -> "x;"
C++
11std::mem_fn
Generalized version of std::mem_fun
.
typedef std::vector<std::shared_ptr<Players>> Players;
void Transform(Players& players, const Transform& t)
{
std::for_each(players.begin(), players.end(),
std::mem_fn(&Player::TransformWith));
}
std::bind
std::bind
std::bind
boost::bind
- boost
version is still boosted with extra featurestemplate <typename Callback>
std::shared_ptr<Button> make_button(Callback callback);
struct Application {
void Quit();
};
Application app;
auto quit = make_button(std::bind(&Application::Quit, &app));
Be sure that the quit button will not be clicked after app
is destroyed.
std::shared_ptr<Application> app;
auto quit = make_button(std::bind(&Application::Quit, app));
auto autosave = make_checkbox(std::bind(&Application::Autosave, app,
std::placeholders::_1));
C#
delegates in C++.
void Function(std::string s, int n, Person p) {
std::cout << p.name() << ": " << s;
while (n-- > 0)
std::cout << '!';
std::cout << std::endl;
}
Person p("Yoda");
auto mega_fun = std::bind(&Function, _2, _1, &p);
mega_fun(3, "The Answer is 42");
// Yoda: The answer is 42!!!
std::function
std::function
is a generic function object.
Let me count the ways ...
void free_function(int x) { std::cout << "free function: " << x << std::endl; }
// ...
void free_with_ud(const UserDefined& ud, int x)
{
std::cout << "free with ud " << &ud << ": " << x << std::endl;
}
// ...
free_function(42);
struct Functor
{
void operator()(int x) const
{
std::cout << "functor " << this << ": " << x << std::endl;
}
};
// ...
Functor functor;
functor(42);
struct UserDefined
{
void method(int x) const
{
std::cout << "method " << this << ": " << x << std::endl;
}
static void static_method(int x)
{
std::cout << "same as free but with access to internals" << std::endl;
}
};
// ...
UserDefined ud;
ud.method(42);
typedef void (*FreeFunctionPtr)(int);
FreeFunctionPtr ffp = &free_function;
ffp(42);
typedef void (UserDefined::*MethodPtr)(int) const;
MethodPtr mp = &UserDefined::method;
(ud.*mp)(42);
UserDefined* udp = &ud;
(udp->*mp)(42);
std::function
std::function<void(int)> generic = free_function;
generic(24);
generic = functor;
generic(2);
std::function
with typesstd::function<void(const UserDefined&, int)> ud_function =
&UserDefined::method;
ud_function(ud, 42);
ud_function = &free_with_ud;
ud_function(ud, 42);
std::function std::bind
generic = std::bind(&UserDefined::method, ud, _1);
generic(4);
generic = std::bind(&UserDefined::method, std::ref(ud), _1);
generic(8);
C++11
template <typename T>
T plus(T lhs, T rhs) {
return lhs + rhs;
}
auto s = plus(2, 2);
Person p1;
Person p2;
auto s = plus(p1, p2)
struct Person
{
Household operator+(const Person&);
}
??? plus(Person lhs, Person rhs) {
return lhs + rhs;
}
auto plus(Person lhs, Person rhs) -> decltype(lhs + rhs)
{
return lhs + rhs;
}
C++14
??? plus(Person lhs, Person rhs)
{
return lhs + rhs;
}
auto plus(Person lhs, Person rhs)
{
return lhs + rhs;
}