// typedef for a point in time
using Time = std::chrono::steady-clock::time_point;
enum class Sound { Beep, Siren, Whistle };
// typedef for a length of time
using Duration = std::chrono::steady_clock::duration;
// at time t, make sound s for duration d
void setAlarm(Time t, Sound s, Duration d);
I. lambda
// setSoundL("L" for "lambda") is a function object allowing a
// sound to be specified for a 30-sec alarm to go off an hour
// after it's set
auto setSoundL = [](Sound s) {
// make std::chrono components available w/o qualification using namespace std::chrono;
setAlarm(steady_clock::now() + hours(1), s, seconds(30));
};
// for C++ 14
auto setSoundL = [](Sound s) {
using namespace std::chrono;
using namespace std::literals;
setAlarm(steady_clock::now() + 1h, s, 30s);
}
II. bind
using namespace std::chrono;
using namespace std::literals;
using namespace std::placeholders;
auto setSoundB = std::bind(setAlarm, steady_clock::now() + 1h, _1, 30s);
“steady_clock::now() + 1h” is passed as an argument to std::bind, not to setAlarm. That means that the expression will be evaluated when std::bind is called.
auto setSoundB = std::bind(setAlarm, std::bind(std::plus<>(), std::bind(steady_clock::now), 1h), _1, 30s);
III. using lambdas generates faster code than using std::bind
setSoundL(Sound::Siren); // body of setAlarm may well be inlined here
setSoundB(Sound::Siren); // body of setAlarm is less likely to be inlined here
inside the call operator for setSoundB, the call to setAlarm takes place through a function pointer. Compiler are less likely to inline function calls through function pointers, and that means that calls to setAlarm through setSoundB are less likelty to be fully inlined than those through setSoundL.
IV. Compilers have no way to determine which of the two setAlarm function they should pass to std::bind
enum class Volum { Normal, Loud, LoudPlusPlus };
void setAlarm(Time t, Sound s, Duration d, Volum v);
auto setSoundL = [](Sound s) {
using namespace std::chrono;
setAlarm(steady_clock::now() + 1h, s, 30s);
};
// error! which setAlarm?
auto setSoundB = std::bind(setAlarm, std::bind(std::plus<>(), std::bind(steady_clock::now), 1h), _1, 30s);
// now okay
using SetAlarm3ParamType = void(*)(Time t, Sound s, Duration d);
auto setSoundB =
std::bind(static_cast<SetAlarm3ParamType>(setAlarm),
std::bind(std::plus<>(),
std::bind(steady_clock::now), 1h), _1, 30s);
Widget w;
using namespace std::placeholders;
auto compressRateB = std::bind(compress, w, -1); // pass by value;
auto compressRateB = std::bind(comperess, std::ref(w), _1); // holds a reference to w
V. C++11 lambdas don’t offer move capture
std::vector<double> data;
auto func = std::bind([](const std::vector<double>& data) { /* uses of data */ },std::move(data)) };
VI. bind an object with a templatized function call operator
class PolyWidget {
puclic:
template<typename T>
void operator() (const T& param) const;
};
PolyWidget pw;
auto boundPW = std::bind(pw, _1);
boundPW(1930);
boundPW(nullptr);
boundPW("Rosebud");
auto boundPW = [pw](const auto& param) { pw(param); }; // C++14