C++函数对象-函数包装器-用作 std::bind 表达式中的未绑定实参的占位符(std::placeholders::_N)

任何定义了函数调用操作符的对象都是函数对象。C++ 支持创建、操作新的函数对象,同时也提供了许多内置的函数对象。

部分函数应用

std::bind_front 与 std::bind 提供部分函数应用的支持,即绑定参数到函数以创建新函数。

用作 std::bind 表达式中的未绑定实参的占位符

std::placeholders::_1, 
std::placeholders::_2, 
..., 
std::placeholders::_N

定义于头文件

/*see below*/ _1;

/*see below*/ _2;
.
.

/*see below*/ _N;

std::placeholders 命名空间含有占位对象 [_1, . . . _N] ,其中 N 是实现定义的最大数字。

于 std::bind 表达式用作参数时,占位符对象被存储于生成的函数对象,而以未绑定参数调用函数对象时,每个占位符 _N 被对应的第 N 个未绑定参数替换。

每个占位符如同以 extern /*unspecified*/ _1; 声明。

(C++17 前)

鼓励实现如同以 inline constexpr /*unspecified*/ _1; 声明占位符,尽管标准仍然允许以 extern /*unspecified*/ _1; 声明它们。

(C++17 起)

占位符对象的类型可默认构造 (DefaultConstructible) 且可复制构造 (CopyConstructible) ,其默认复制/移动构造函数不抛异常,且对于任何占位符 _N ,类型 std::is_placeholder 有定义且从 std::integral_constant 导出。

定义

  namespace placeholders
  {
  _GLIBCXX_BEGIN_NAMESPACE_VERSION
  /* Define a large number of placeholders. There is no way to
   * simplify this with variadic templates, because we're introducing
   * unique names for each.
   */
    extern const _Placeholder<1> _1;
    extern const _Placeholder<2> _2;
    extern const _Placeholder<3> _3;
    extern const _Placeholder<4> _4;
    extern const _Placeholder<5> _5;
    extern const _Placeholder<6> _6;
    extern const _Placeholder<7> _7;
    extern const _Placeholder<8> _8;
    extern const _Placeholder<9> _9;
    extern const _Placeholder<10> _10;
    extern const _Placeholder<11> _11;
    extern const _Placeholder<12> _12;
    extern const _Placeholder<13> _13;
    extern const _Placeholder<14> _14;
    extern const _Placeholder<15> _15;
    extern const _Placeholder<16> _16;
    extern const _Placeholder<17> _17;
    extern const _Placeholder<18> _18;
    extern const _Placeholder<19> _19;
    extern const _Placeholder<20> _20;
    extern const _Placeholder<21> _21;
    extern const _Placeholder<22> _22;
    extern const _Placeholder<23> _23;
    extern const _Placeholder<24> _24;
    extern const _Placeholder<25> _25;
    extern const _Placeholder<26> _26;
    extern const _Placeholder<27> _27;
    extern const _Placeholder<28> _28;
    extern const _Placeholder<29> _29;
  _GLIBCXX_END_NAMESPACE_VERSION
  }

调用示例

#include 
#include 
#include 

struct Cell
{
    int x;
    int y;

    Cell() = default;
    Cell(int a, int b): x(a), y(b) {}
    Cell(const Cell &cell)
    {
        x = cell.x;
        y = cell.y;
    }

    bool operator <(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y < cell.y;
        }
        else
        {
            return x < cell.x;
        }
    }

    Cell &operator+(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }
};
namespace std
{
namespace placeholders
{
extern const _Placeholder<1024> _1024;
}
}

std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
    os << "{" << cell.x << "," << cell.y << "}";
    return os;
}

void Function1(Cell cell1, Cell cell2, Cell cell3, const Cell& cell4, Cell cell5)
{
    std::cout << cell1 << ' ' << cell2 << ' ' << cell3 << ' '
              << cell4 << ' ' << cell5 << std::endl;
}

int main()
{
    std::cout << "Standard placeholder _1 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _2 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _4 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _5 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _8 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _16 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _17 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _18 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _20 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _24 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _28 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _29 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;
    std::cout << "Standard placeholder _1024 is for the argument number: "
              << std::is_placeholder::value
              << std::endl;

    std::cout << std::endl;
    // 演示参数重排序和按引用传递
    Cell cell1 = {101, 101};
    // ( _1 与 _2 来自 std::placeholders ,并表示将来会传递给 f1 的参数)
    auto function1 = std::bind(Function1, std::placeholders::_2,
                               Cell{102, 102}, std::placeholders::_1, std::cref(cell1), cell1);
    cell1 = {1024, 1024};
    // Cell{103, 103} 为 _1 所绑定, Cell{104, 104} 为 _2 所绑定,不使用 Cell{105, 105}
    // 进行到 Function1(Cell{104, 104}, Cell{102, 102}, Cell{103, 103}, cell1, Cell{101, 101}) 的调用
    function1(Cell{103, 103}, Cell{104, 104}, Cell{105, 105});

    return 0;
}

输出

Standard placeholder _1 is for the argument number: 1
Standard placeholder _2 is for the argument number: 2
Standard placeholder _4 is for the argument number: 4
Standard placeholder _5 is for the argument number: 5
Standard placeholder _8 is for the argument number: 8
Standard placeholder _16 is for the argument number: 16
Standard placeholder _17 is for the argument number: 17
Standard placeholder _18 is for the argument number: 18
Standard placeholder _20 is for the argument number: 20
Standard placeholder _24 is for the argument number: 24
Standard placeholder _28 is for the argument number: 28
Standard placeholder _29 is for the argument number: 29
Standard placeholder _1024 is for the argument number: 1024

{104,104} {102,102} {103,103} {1024,1024} {101,101}

你可能感兴趣的:(#,部分函数应用,c++,标准库模板,STL,函数对象,部分函数应用,placeholders)