Skip to content

Latest commit

ย 

History

History
103 lines (72 loc) ยท 3.63 KB

ITEM27.md

File metadata and controls

103 lines (72 loc) ยท 3.63 KB

Universal reference ์˜ค๋ฒ„๋กœ๋”ฉ์— ๋Œ€ํ•œ ๋Œ€์•ˆ

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