ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄/C++ μ‘μš©

[STL][functional] std::bind, std::function

μ„œμ•„λž‘πŸ˜ 2023. 6. 8. 00:15

 

 

# std::bind, std::function

std::bind ν•¨μˆ˜ ν…œν”Œλ¦Ώμ€ ν•¨μˆ˜λ‚˜ ν•¨μˆ˜ 객체λ₯Ό 더 μž‘μ€ 인자 리슀트둜 λ°”μΈλ”©ν•˜μ—¬ μƒˆλ‘œμš΄ ν•¨μˆ˜λ‚˜ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•œλ‹€. μ΄λŠ” 미리 μ§€μ •ν•œ 인자 κ°’μ΄λ‚˜ 인자 μœ„μΉ˜μ— 값을 κ³ μ •μ‹œν‚€λŠ” 데 μ‚¬μš©λœλ‹€. std::bindλ₯Ό μ‚¬μš©ν•˜λ©΄ 인자λ₯Ό 일뢀 κ³ μ •ν•˜κ±°λ‚˜ μˆœμ„œλ₯Ό λ³€κ²½ν•˜μ—¬ ν•¨μˆ˜ 호좜 μ‹œ μœ μ—°μ„±μ„ 높일 수 μžˆλ‹€.

std::function은 ν•¨μˆ˜ 포인터와 λΉ„μŠ·ν•œ κ°œλ…μœΌλ‘œ, μ‹€ν–‰ κ°€λŠ₯ν•œ 객체λ₯Ό λ‚˜νƒ€λ‚΄λŠ” ν•¨μˆ˜ 객체(wrapper)이닀. λ‹€μ–‘ν•œ μ’…λ₯˜μ˜ ν•¨μˆ˜λ‚˜ ν•¨μˆ˜ 객체λ₯Ό μ €μž₯ν•˜κ³  ν˜ΈμΆœν•  수 있으며, 특히 λŸ°νƒ€μž„ μ‹œμ— λ‹€λ₯Έ ν•¨μˆ˜λ‚˜ ν•¨μˆ˜ 객체λ₯Ό ν• λ‹Ήν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€.

std::bind와 std::function은 μ„œλ‘œ ꢁ합이 잘 λ§žλŠ”λ‹€. 특히 ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ—μ„œ 강점을 보인닀.

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>

double divMe(double a, double b){
  return double(a/b);
}

using namespace std::placeholders;

int main(){

  std::cout << std::endl;

  // invoking the function object directly
  std::cout << "1/2.0= " << std::bind(divMe, 1, 2.0)() << std::endl;

  // placeholders for both arguments
  std::function<double(double, double)> myDivBindPlaceholder= std::bind(divMe, _1, _2);
  std::cout << "1/2.0= " << myDivBindPlaceholder(1, 2.0) << std::endl;

  // placeholders for both arguments, swap the arguments
  std::function<double(double, double)> myDivBindPlaceholderSwap= std::bind(divMe, _2, _1);
  std::cout << "1/2.0= " << myDivBindPlaceholderSwap(2.0, 1) << std::endl;

  // placeholder for the first argument
  std::function<double(double)> myDivBind1St= std::bind(divMe, _1, 2.0);
  std::cout<< "1/2.0= " << myDivBind1St(1) << std::endl;

  // placeholder for the second argument
  std::function<double(double)> myDivBind2Nd= std::bind(divMe, 1.0, _1);
  std::cout << "1/2.0= " << myDivBind2Nd(2.0) << std::endl;

  std::cout << std::endl;

}

/*
1/2.0= 0.5
1/2.0= 0.5
1/2.0= 0.5
1/2.0= 0.5
1/2.0= 0.5
*/

 

std::bind의 νŠΉμ§•μ€ λ‹€μŒκ³Ό κ°™λ‹€.

- 인수λ₯Ό μ›ν•˜λŠ” μœ„μΉ˜μ— 바인딩할 수 μžˆλ‹€.
- 인수의 μˆœμ„œλ₯Ό λ°”κΏ€ 수 μžˆλ‹€.
- μΈμˆ˜μ— 자리 ν‘œμ‹œμž(placeholder)λ₯Ό μ μš©ν•  수 μžˆλ‹€.
- ν•¨μˆ˜μ˜ μΌλΆ€λΆ„λ§Œ 평가할 수 μžˆλ‹€.
- μƒˆλ‘œ μƒμ„±λœ ν•¨μˆ˜ 였브젝트λ₯Ό ν˜ΈμΆœν•˜κ³  std::function에 μ €μž₯ν•  수 μžˆλ‹€.

 

std::function은 μž„μ˜μ˜ μ½œλŸ¬λΈ”(ν•¨μˆ˜ ν˜•νƒœμ˜ 호좜자)을 λ³€μˆ˜μ— μ €μž₯ν•  수 μžˆλ‹€. μ½œλŸ¬λΈ”μ€ 일반 ν•¨μˆ˜λΏλ§Œ μ•„λ‹ˆλΌ λžŒλ‹€ ν•¨μˆ˜ ν˜Ήμ€ ν•¨μˆ˜ 였브젝트일 μˆ˜λ„ μžˆλ‹€.

#include <cmath>
#include <functional>
#include <iostream>
#include <map>

int main(){

  std::cout << std::endl;

  // dispatch table
  std::map< const char , std::function<double(double, double)> > dispTable;
  dispTable.insert( std::make_pair('+', [](double a, double b){ return a + b;}));
  dispTable.insert( std::make_pair('-', [](double a, double b){ return a - b;}));
  dispTable.insert( std::make_pair('*', [](double a, double b){ return a * b;}));
  dispTable.insert( std::make_pair('/', [](double a, double b){ return a / b;}));

  // do the math
  std::cout << "3.5 + 4.5= " << dispTable['+'](3.5, 4.5) << std::endl;
  std::cout << "3.5 - 4.5= " << dispTable['-'](3.5, 4.5) << std::endl;
  std::cout << "3.5 * 4.5= " << dispTable['*'](3.5, 4.5) << std::endl;
  std::cout << "3.5 / 4.5= " << dispTable['/'](3.5, 4.5) << std::endl;

  // add a new operation
  dispTable.insert( std::make_pair('^', [](double a, double b){ return std::pow(a, b); }));
  std::cout << "3.5 ^ 4.5= " << dispTable['^'](3.5, 4.5) << std::endl;

  std::cout << std::endl;

};

/*
3.5 + 4.5= 8
3.5 - 4.5= -1
3.5 * 4.5= 15.75
3.5 / 4.5= 0.777778
3.5 ^ 4.5= 280.741
*/