Effective Modern C++ 34. Prefer lambdas to std::bind
2018-01-26 11:01
351 查看
// 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
4000
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
相关文章推荐
- Effective Modern C++ 条款34 比起std::bind更偏向使用lambda
- Effective Modern C++ 42 Specific Ways to Improve Your Use of C++11 and C++14
- Effective Modern C++ 条款36 如果异步执行是必需的,指定std::launch::async策略
- Effective Modern C++ 条款23 理解std::move和std::forward
- Effective modern C++ 条款37:基于任务编程优先于基于线程编程(Prefer task-based programming to thread-based)
- Effective Modern C++ 条款20 把std::weak_ptr当作类似std::shared_ptr的、可空悬的指针使用
- <Effective Modern C++>Item 18: Use std::unique_ptr for exclusive-ownership resource management.
- Effective modern C++ 条款 38:如果异步至关重要请指定std::launch::async
- Effective Modern C++ 条款19 用std::shared_ptr管理共享所有权的资源
- Effective Modern C++ 36. Specify std::launch::async if asynchronicity is essential
- Item34 Prefer lambdas to std::bind
- Effective Modern C++ 条款33 对需要std::forward的auto&&参数使用decltype
- Effective Modern C++ 条款37 在所有路径上,让std::thread对象变得不可连接(unjoinable)
- Effective Modern C++ 条款18 用std::unique_ptr管理独占所有权的资源
- Effective modern C++ 条款 39:让std::thread在所有路径上不可join(Make std::threads unjoinable on all paths)
- Effective Modern C++ 条款25 对右值引用使用std::move,对通用引用使用std::forward
- Effective Modern C++ 条款21 比起直接使用new,更偏爱使用std::make_unique和std::make_shared
- 实战c++中的string系列--std:vector<char> 和std:string相互转换(vector to stringstream)
- C++出现to_string is not a member of std 或者 to_string was not declared in this scope的解决方法
- 《Effective Modern C++》翻译--条款2: 理解auto自动类型推导