Universal reference๋ฅผ ์ค๋ฒ๋ก๋ฉํ๋ ๊ฒ์ ๋ง์ ๋ฌธ์ ๋ฅผ ์ผ์ผํจ๋ค. ํ์ง๋ง ์ค๋ฒ๋ก๋ฉ์ด ์ ์ฉํ ๊ฒฝ์ฐ์ ๋ํ ์๋ ๋ณด์ฌ
์ฃผ์๋ค.
์ด ์ฅ์์๋ universal reference๋ฅผ ์ค๋ฒ๋ก๋ฉํ์ง ์๋๋ก ๋์์ธ ํ๊ฑฐ๋, ํ๋๋ผ๋ ์ธ์ ํ์ ์ ์ ์ฝ์ ๊ฑธ์ด์ ์ํ
๋ ๋ฐฉํฅ์ผ๋ก ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ์์๋ณธ๋ค.
์ค๋ฒ๋ก๋ฉ ํฌ๊ธฐํ๊ธฐ
์๋ฅผ๋ค์ด logAndAdd ํจ์๋ฅผ ์ค๋ฒ๋ก๋ฉํ์ง ์๊ณ logAndAddName๊ณผ logAndAddNameIdx๋ก ๋๋์ด ๊ตฌํํ๋ ๋ฐฉ
๋ฒ์ด๋ค. ํ์ง๋ง constructor์ ๊ฐ์ด ์ด๋ฆ์ด ์ ํด์ ธ ์๋ ๊ฒฝ์ฐ์๋ ์ธ ์ ์๊ณ , ๋ ๋๊ฐ ์ค๋ฒ๋ก๋ฉ์ ํฌ๊ธฐํ๊ณ ์ถ๊ฒ ๋
๊ฐ?
** Pass by const T& **
Pass-by-universal-reference๋ฅผ ์ฌ์ฉํ์ง ์๊ณ pass-by-lvalue-reference-to-const๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ. C++98๋ก ๋
์๊ฐ ์ด ๋ฐฉ๋ฒ์ ์ ๋์ํ์ง๋ง ์ฑ๋ฅ ๊ฐ์ ์ ํฌ๊ธฐํ ๋ฐฉ๋ฒ์ด๋ค: Move๋ emplace ์ฅ์ ์ ํ์ฉํ ์ ์๋ค.
** Pass by value **
์ฑ๋ฅ ํฅ์ ์ด์ ๋ ํญ๋ชฉ 41์ ์ค๋ช ํฉ๋๋ค. ์ด ๋ฐฉ๋ฒ์ universal reference๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๊ทธ๋ฅ pass-by-value๋ก ๋
์ด์จ parameter๋ฅผ std::move๋ก ์ ํํด์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
class Person {
public:
explicit Person(std::string n)
: name(std::move(n)) {}
explicit Person(int idx)
: name(nameFromIdx(idx)) {}
โฆ
private:
std::string name;
};์ฌ๊ธฐ์ std::size_t, short, long ํ์ ์ ์ธ์๊ฐ ๋์ด์ค๋ฉด int๋ฅผ ๋ฐ๋ ํจ์๊ฐ call๋๊ฒ ๋ฉ๋๋ค.
** Tag dispatch ํ์ฉ **
์์์ ์ดํด๋ณธ pass by lvalue reference to const์ pass by value ๋ฐฉ๋ฒ์ perfect forwarding์ ์ง์ํ์ง ์์ต๋
๋ค. Universal reference๋ฅผ ์ฌ์ฉํ๋ ค๋ ๋ชฉ์ ์ด perfect forwarding์ ํ์ฉํ๋ ๊ฒ์ด์๋ค๋ฉด universal reference๋ฅผ
์ฌ์ฉํ๋ ๊ฒ ๋ง๊ณ ๋ ๋์์ด ์์ต๋๋ค. ํ์ง๋ง ์ค๋ฒ๋ก๋ฉ๋ ํฌ๊ธฐํ๊ณ ์ถ์ง ์๋ค๋ฉด ์ด๋ค ๋ฐฉ๋ฒ์ด ์์๊น์?
๋ฐฉ๋ฒ์ ์ค๋ฒ๋ก๋ฉ ๋ ํจ์ ํธ์ถ ์ param/arg ์กฐํฉ์ ์ต๊ณ ๋งค์นญ์ ์ ํํ๋ ์ ์ ์ด์ฉํ๋ ๊ฒ์ ๋๋ค.
std::multiset<std::string> names;
template<typename T>
void logAndAdd(T&& name)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(std::forward<T>(name));
}์ด ํจ์๋ ์ ๋์ํ๊ฒ ์๋ง int ์ธ์๋ฅผ ๋ฐ๋ ํจ์๋ฅผ ์ค๋ฒ๋ก๋ฉํ๋ฉด ๋ฌธ์ ๊ฐ ์๊ฒผ์์ง์? ์ด๋ฅผ ํํผํ๊ธฐ ์ํด์, ์ค๋ฒ
๋ก๋ฉ์ ํ์ง ๋ง๊ณ ๊ฐ๊ฐ integral ๊ฐ๊ณผ ๋ค๋ฅธ ๋ชจ๋ ๊ฐ์ ๋ค๋ฃจ๋ ๋๊ฐ์ ํจ์์ delegateํ๋ logAndAdd๋ฅผ ์ฌ ๊ตฌํํ
๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด ๋ด ์๋ค. ์ค์ ์ผ์ ํ๋ ํจ์๋ logAndAddImpl ํ๋๋ก ์ด๋ฆ์ ์ง๊ณ ์, ์ฌ๊ธฐ์ ์ค๋ฒ๋ก๋ฉ์ ํ ๊ฒ
์ ๋๋ค. ์ค๋ฒ๋ก๋ฉ๋ ํ๋์ ํจ์๋ Universal reference๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋๊น ๊ฒฐ๊ตญ ์ค๋ฒ๋ก๋ฉ๊ณผ universal reference๋ฅผ
๋ชจ๋ ํ์ฉํ๊ฒ ๋๊ฒ ๋ค์. ์ค์ํ ๋ถ๋ถ์ ๋๊ฐ์ ์ค๋ฒ๋ก๋ฉ ํจ์์ ๋๋ฒ์งธ param ๊ฐ์ผ๋ก ์ธ์๊ฐ integral ๊ฐ์ธ์ง ์๋์ง๋ฅผ ๋ฐ์ ๊ฒ์ ๋๋ค.
template<typename T>
void logAndAdd(T&& name)
{
logAndAddImpl(std::forward<T>(name),
std::is_integral<T>()); // not quite correct
}template<typename T>
void logAndAdd(T&& name)
{
logAndAddImpl(std::forward<T>(name),
std::is_integral<typename std::remove_reference<T>::type>());
}
template<typename T>
void logAndAddImpl(T&& name, std::false_type)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(std::forward<T>(name));
}