Skip to content

Latest commit

ย 

History

History
204 lines (136 loc) ยท 6.26 KB

File metadata and controls

204 lines (136 loc) ยท 6.26 KB

std::bind ๋ณด๋‹ค lamda๋ฅผ ์„ ํ˜ธํ•˜๋ผ

std::bind๋Š” TR1 ์žฌ์ • ์ดํ›„๋กœ ์˜ค๋žซ๋™์•ˆ ์กด์žฌํ•ด ์™€์„œ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ต์ˆ™ํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ C++11๊ณผ C++14๋ถ€ํ„ฐ๋Š”

lamda๊ฐ€ ๊ฑฐ์˜ ์–ธ์ œ๋‚˜ ๋” ๊ฐ•๋ ฅํ•˜๋‹ค. ์ด๋ฒˆ ํ•ญ๋ชฉ์—์„œ๋Š” lamda๋ฅผ ์„ ํ˜ธํ•˜๋Š” ์ด์œ ๋ฅผ ์•Œ์•„๋ณธ๋‹ค.

๋” ๋‚˜์€ ๊ฐ€๋…์„ฑ

using Time = std::chrono::steady_clock::time_point;

enum class Sound { Beep, Siren, Whistle };

using Duration = std::chrono::steady_clock::duration;

void setAlarm(Time t, Sound s, Duration d);

ํ•œ์‹œ๊ฐ„ ํ›„์— 30์ดˆ ๋™์•ˆ ์šธ๋ฆฌ๋Š” ์•Œ๋žŒ์„ ์„ธํŒ…ํ•˜๋ ค๊ณ  ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž. ์—ฌ๊ธฐ์„œ ์•Œ๋žŒ ์‹œ๊ฐ„๊ณผ ์šธ๋ฆฌ๋Š” ๊ธฐ๊ฐ„์€ ์ด๋ฏธ ์ •ํ•ด์ ธ

์žˆ๋‹ค. ์‚ฌ์šด๋“œ์˜ ์ข…๋ฅ˜๋งŒ ๋ฏธ๋ฆฌ ๊ฒฐ์ •๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค.

์ด์— Sound ๊ฐ’๋งŒ ๋ฐ›์•„์„œ ์•Œ๋žŒ์„ ์„ค์ •ํ•˜๋Š” wrapper๋ฅผ ๋งŒ๋“ค๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋จผ์ € lamda๋Š”:

auto setSoundL = [](Sound s) {
  using namespace std::chrono;

  setAlarm(steady_clock::now() + hours(1),
           s,
           seconds(30));
};

๋‹ค์Œ์œผ๋กœ ์ด๊ฒƒ์„ std::bind ๋ฒ„์ „์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๋ชจ์–‘์ด ๋‚˜์˜จ๋‹ค:

using namespace std::chrono;
using namespace std::literals;

using namespace std::placeholders;

auto setSoundB =
  std::bind(setAlarm,
            steady_clock::now() + 1h,
            _1,
            30s);
  • ์ฒซ๋ฒˆ์งธ๋กœ setSoundL์€ param ํƒ€์ž…์„ ๋ช…์‹œ์ ์œผ๋กœ ์•Œ ์ˆ˜ ์žˆ๋Š”๋ฐ ๋ฐ˜ํ•ด์„œ setSoundB๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋Š” placeholder

_1์˜ ํƒ€์ž…์ด ๋ฌด์–ธ์ง€ ์•Œ๊ธฐ ์œ„ํ•ด์„œ setAlarm์˜ ์‹œ๊ทธ๋„ˆ์ฒ˜๋ฅผ ํ™•์ธํ•ด ๋ณด์•„์•ผ ํ•œ๋‹ค.

  • ๋‘๋ฒˆ์งธ๋กœ lamda์—์„œ๋Š” ํ‘œํ˜„์‹ โ€œsteady_clock::now() + 1hโ€๊ฐ€ setAlarm์œผ๋กœ ์ง์ ‘ ๋„˜์–ด๊ฐ€๋Š” ๋ฐ˜๋ฉด์— std::bind์˜

๊ฒฝ์šฐ โ€œsteady_clock::now() + 1hโ€๊ฐ€ std::bind์˜ ์ธ์ž๋กœ ๋„˜์–ด๊ฐ„๋‹ค. ์ฆ‰, ์ „๋‹ฌ๋œ ํ‘œํ˜„์‹์ด std::bind๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ํ•ด์„

๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ๊ฒฝ์šฐ ์•Œ๋žŒ์ด setAlarm ์‹คํ–‰ ํ›„ ํ•œ์‹œ๊ฐ„์ด ์•„๋‹Œ std::bind call ํ›„ ํ•œ์‹œ๊ฐ„ ํ›„์— ์šธ๋ฆฌ๊ฒŒ ๋œ๋‹ค. ์ด์— ๋Œ€ํ•œ

ํ•ด๊ฒฐ์ฑ…์ด ์žˆ๋Š”๋ฐ ํ‘œํ˜„์‹์˜ ํ•ด์„์„ ์—ฐ๊ธฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค:

using namespace std::chrono;
using namespace std:: placeholders;

auto setSoundB =
  std::bind(setAlarm,
            std::bind(std::plus<steady_clock::time_point>(),
                      steady_clock::now(),
                      hours(1)),
            _1,
            seconds(30));

๋‹ค์Œ์œผ๋กœ setAlarm์ด ์˜ค๋ฒ„๋กœ๋”ฉ ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋” ์ƒ๊ฐํ•ด ๋ณด์ž. ์—ฌ๊ธฐ์„œ ์ถ”๊ฐ€์ ์ธ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

enum class Volume { Normal, Loud, LoudPlusPlus };

void setAlarm(Time t, Sound s, Duration d, Volume v);

Lamda์˜ ๊ฒฝ์šฐ ์˜ค๋ฒ„๋กœ๋”ฉ resolution์ด ์ธ์ž 3๊ฐœ์งœ๋ฆฌ setAlarm์„ ์„ ํƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋Œ€๋กœ ์ž˜ ๋™์ž‘ํ•œ๋‹ค. ๋ฐ˜๋ฉด์—

std::bind์˜ ๊ฒฝ์šฐ ์ฃผ์–ด์ง„ ์ •๋ณด๊ฐ€ setAlarm ํ•จ์ˆ˜ ์ด๋ฆ„๋ฐ–์— ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด

์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์›ํ•˜๋Š” ํ•จ์ˆ˜ ํฌ์ธํ„ฐ ํ˜•์‹์œผ๋กœ ์บ์ŠคํŒ…์„ ํ•ด์•ผํ•œ๋‹ค:

using SetAlarm3ParamType = void(*)(Time t, Sound s, Duration d);

auto setSoundB =
  std::bind(static_cast<SetAlarm3ParamType>(setAlarm),
            std::bind(std::plus<>,
                      steady_clock::now(),
                      h1),
            _1,
            30s);
  • ์—ฌ๊ธฐ์„œ ํ•œ๊ฐ€์ง€ ์ฐจ์ด์ ์ด ๋˜ ๋ฐœ์ƒํ•œ๋‹ค. Lamda์˜ ๊ฒฝ์šฐ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœํ•˜๋Š” setAlarm์ด ์ผ๋ฐ˜ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ

์ผ๋Ÿฌ๊ฐ€ inline ํ•จ์ˆ˜๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋ฉด์— std::bind์˜ ๊ฒฝ์šฐ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ํ†ตํ•ด์„œ ํ˜ธ์ถœ์ด ๋˜๋Š”๋ฐ ์ด ๊ฒฝ์šฐ ์ปดํŒŒ์ผ

๋Ÿฌ๊ฐ€ inline์œผ๋กœ ์ƒ์„ฑํ•  ํ™•๋ฅ ์€ ๋งŽ์ด ๋‚ฎ์•„์ง„๋‹ค. ์ฆ‰, Lamda๋กœ ์ž‘์„ฑํ–ˆ์„ ๋•Œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋” ํšจ์œจ์ ์ธ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•  ํ™•

๋ฅ ์ด ๋†’๋‹ค.

๋‹จ์ˆœํ•œ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ์•„๋‹Œ ์ข€ ๋” ๋ณต์žกํ•œ ์ƒํ™ฉ์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด std::bind๋Š” ๋” ๋ณต์žกํ•ด ์ง„๋‹ค.

auto betweenL =
  [lowVal, highVal]
  (const auto& val)
  { return lowVal <= val && val <= highVal; };
using namespace std::placeholders;

auto betweenB =
  std::bind(std::logical_and<bool>(),
            std::bind(std::less_euqal<int>(), lowVal, _1),
            std::bind(std::less_equal<int>(), _1, highVal));

Lamda ๋ฒ„์ „์ด ๋” ์งง์„๋ฟ ์•„๋‹ˆ๋ผ ๋” ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์‰ฝ๋‹ค๋Š”๋ฐ ๋™์˜ํ•˜๊ธฐ ๋ฐ”๋ž€๋‹ค. :)

std::bind์˜ ์ธ์ž ์ „๋‹ฌ ๋ฐฉ์‹

enum class CompLevel { Low, Normal, High };

Widget compress(const Widget& w,
                CompLevel lev);

Widget w;

using namespace std::placeholders;

auto compressRateB = std::bind(compress, w, _1);

์—ฌ๊ธฐ์„œ w๋Š” compressRateB๊ฐ€ ๋งŒ๋“  bind object์— ์ €์žฅ๋˜๋Š”๋ฐ ๊ฐ’์€ by value๋กœ ๋„˜์–ด๊ฐ„๋‹ค. std::bind์˜ ๊ฒฝ์šฐ ์ด๋ ‡

๊ฒŒ ๋™์ž‘ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ˆ™์ง€ํ•˜๊ณ  ์žˆ์„ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. ํ•˜์ง€๋งŒ lamda์˜ ๊ฒฝ์šฐ capture ๋ฐฉ์‹์ด ๋ช…์‹œ์ ์ด๋‹ค.

auto compressRateL =
  [w](CompLevel lev)
  { return compress(w, lev); };

ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„˜๊ธฐ๋Š” ๊ฒƒ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค. Lamda์˜ ๊ฒฝ์šฐ:

compressRateL(CompLevel::Hight);

์ด ์˜ˆ์—์„œ๋Š” by value๋กœ ๋„˜์–ด๊ฐ€๋Š” ๊ฒƒ์ด ๋ช…ํ™•ํ•˜๊ณ , ๊ตฌํ˜„์ž์˜ ์˜๋„๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ˜์˜ํ•œ๋‹ค. ๋ฐ˜๋ฉด std::bind์˜ ๊ฒฝ์šฐ:

compressRateB(CompLevel::High);

๋ช…์‹œ์ ์œผ๋กœ ํ‘œํ˜„๋˜์ง€ ์•Š๋Š”๋‹ค. std::bind๋ฅผ ํ†ตํ•ด bind object์— ๋„˜์–ด๊ฐ€๋Š” ๋ชจ๋“  parameter๋Š” by reference๋กœ ๋„˜์–ด๊ฐ„

๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ๋Š” ๋ฐฉ๋ฒ•๋ฐ–์— ์—†๋‹ค.

Lamda์— ๋น„ํ•ด์„œ std::bind๋Š” ์ฝ๊ธฐ ์–ด๋ ต๊ณ , ํ‘œํ˜„ํ•˜๊ธฐ ์–ด๋ ต๊ณ  ๋œ ํšจ์œจ์ ์ด๋‹ค. std::bind๋Š” C++14์—์„œ๋Š” ํ•ฉ๋ฆฌ์ ์ธ

use case๊ฐ€ ์—†๋‹ค. ๋‹ค๋งŒ C++11์—์„œ๋Š” ๋‘๊ฐ€์ง€ ์ œ์•ฝ์ ์ธ ์ƒํ™ฉ์—์„œ๋Š” ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค:

  • Move capture: C++11 lamda๋Š” move capture๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • Polymorphic function objects
class PolyWidget {
public:
  template<typename T>
  void operator()(const T& param);
  ...
};

PolyWidget pw;

auto boundPW = std::bind(pw, _1);

boundPW(1930);

boundPW(nullptr);

boundPW("Rosebud");

C++11 lamda์—์„œ๋Š” ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์—ˆ๋‹ค. ํ•˜์ง€๋งŒ C++14 ๋ถ€ํ„ฐ๋Š” auto paramter๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฅผ ๊ฐ„

๋‹จํžˆ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค:

auto boundPW = [pw](const auto& param)
               { pw(param); };