๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด/C++ ์‘์šฉ

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

by ์„œ์•„๋ž‘๐Ÿ˜ 2023. 6. 8.

 

 

# 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
*/

 

 

 

๋Œ“๊ธ€