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

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

部分函数应用

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

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

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

定义于头文件 <functional>

/*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<decltype(_N)> 有定义且从 std::integral_constant<int, N> 导出。

定义

  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 <iostream>
#include <type_traits>
#include <functional>

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<decltype(std::placeholders::_1)>::value
              << std::endl;
    std::cout << "Standard placeholder _2 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_2)>::value
              << std::endl;
    std::cout << "Standard placeholder _4 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_4)>::value
              << std::endl;
    std::cout << "Standard placeholder _5 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_5)>::value
              << std::endl;
    std::cout << "Standard placeholder _8 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_8)>::value
              << std::endl;
    std::cout << "Standard placeholder _16 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_16)>::value
              << std::endl;
    std::cout << "Standard placeholder _17 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_17)>::value
              << std::endl;
    std::cout << "Standard placeholder _18 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_18)>::value
              << std::endl;
    std::cout << "Standard placeholder _20 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_20)>::value
              << std::endl;
    std::cout << "Standard placeholder _24 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_24)>::value
              << std::endl;
    std::cout << "Standard placeholder _28 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_28)>::value
              << std::endl;
    std::cout << "Standard placeholder _29 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_29)>::value
              << std::endl;
    std::cout << "Standard placeholder _1024 is for the argument number: "
              << std::is_placeholder<decltype(std::placeholders::_1024)>::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}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值