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); };