C++函数对象-引用包装器-可复制构造 (CopyConstructible) 且可复制赋值 (CopyAssignable) 的引用包装器(std::reference_wrapper)(二)

本文详细介绍了C++中的std::reference_wrapper,一种用于存储和操作可复制函数对象的引用包装器,包括构造、复制、调用示例以及推导指引等关键特性。
摘要由CSDN通过智能技术生成

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

引用包装器


引用包装器允许存储引用到可复制的函数对象中:

可复制构造 (CopyConstructible) 且可复制赋值 (CopyAssignable) 的引用包装器

std::reference_wrapper

template< class T >
class reference_wrapper;

(C++11 起)

std::reference_wrapper 是包装引用于可复制、可赋值对象的类模板。它常用作将容器存储入无法正常保有引用的标准容器(类似 std::vector )的机制。

存储引用于新的 std::reference_wrapper 对象

std::reference_wrapper<T>::reference_wrapper

template< class U >
reference_wrapper( U&& x ) noexcept(/*see below*/) ;

(1)

reference_wrapper( const reference_wrapper& other ) noexcept;

(2)

构造新的 reference_wrapper 。

1) 如同用 T& t = std::forward<U>(x); 转换 xT& ,然后存储到 t 的引用。此重载仅若 typename std::decay<U>::type 与 reference_wrapper 不是同一类型且表达式 FUN(std::declval<U>()) 为良式才参与重载决议,其中 FUN 指名虚构函数集

void FUN(T&) noexcept;
void FUN(T&&) = delete;

2) 复制构造函数。存储到 other.get() 的引用。

参数

x-要包装的对象
other-另一 reference_wrapper

异常

1)noexcept 规定:  

noexcept(noexcept(FUN(std::declval<U>())))

,其中 FUN 是以上描述中的虚构函数集。

调用示例

#include <algorithm>
#include <list>
#include <vector>
#include <iostream>
#include <numeric>
#include <random>
#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;
    }

    Cell &operator*=(int n)
    {
        x *= n;
        y *= n;
        return *this;
    }

    Cell &operator++()
    {
        x += 1;
        y += 1;
        return *this;
    }
};

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

int main()
{
    Cell cell1 = {1024, 1024};
    std::reference_wrapper<Cell> reference_wrapper(cell1);
    std::cout << "reference_wrapper: " << reference_wrapper << std::endl;
    cell1 = {1025, 1025};
    std::cout << "reference_wrapper: " << reference_wrapper << std::endl;
    std::cout << "cell1: " << cell1 << std::endl;

    return 0;
}

输出

reference_wrapper: {1024,1024}
reference_wrapper: {1025,1025}
cell1: {1025,1025}

重绑定 std::reference_wrapper

std::reference_wrapper<T>::operator=

reference_wrapper& operator=( const reference_wrapper<T>& other ) noexcept;

(C++11 起)

复制赋值运算符。丢弃当前引用,并存储到 other.get() 的引用。

参数

other-要复制的 reference_wrapper

返回值

*this

调用示例

#include <algorithm>
#include <list>
#include <vector>
#include <iostream>
#include <numeric>
#include <random>
#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;
    }

    Cell &operator*=(int n)
    {
        x *= n;
        y *= n;
        return *this;
    }

    Cell &operator++()
    {
        x += 1;
        y += 1;
        return *this;
    }
};

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

int main()
{
    Cell cell1 = {1024, 1024};
    std::cout << "cell1: " << cell1 << std::endl;
    std::reference_wrapper<Cell> reference_wrapper1(cell1);
    std::reference_wrapper<Cell> reference_wrapper2 = reference_wrapper1;
    std::cout << "reference_wrapper1: " << reference_wrapper1 << std::endl;
    std::cout << "reference_wrapper2: " << reference_wrapper2 << std::endl;

    cell1 = {1025, 1025};
    std::cout << "cell1: " << cell1 << std::endl;
    std::cout << "reference_wrapper1: " << reference_wrapper1 << std::endl;
    std::cout << "reference_wrapper2: " << reference_wrapper2 << std::endl;

    return 0;
}

输出

cell1: {1024,1024}
reference_wrapper1: {1024,1024}
reference_wrapper2: {1024,1024}
cell1: {1025,1025}
reference_wrapper1: {1025,1025}
reference_wrapper2: {1025,1025}

访问存储的引用

std::reference_wrapper<T>::get, 
std::reference_wrapper<T>::operator T&

operator T& () const noexcept;

(C++11 起)

T& get() const noexcept;

(C++11 起)

返回存储的引用。

参数

(无)

返回值

存储的引用。

调用示例

#include <algorithm>
#include <list>
#include <vector>
#include <iostream>
#include <numeric>
#include <random>
#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;
    }

    Cell &operator*=(int n)
    {
        x *= n;
        y *= n;
        return *this;
    }

    Cell &operator++()
    {
        x += 1;
        y += 1;
        return *this;
    }
};

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

int main()
{
    Cell cell1 = {1024, 1024};
    std::cout << "cell1: " << cell1 << std::endl;
    std::reference_wrapper<Cell> reference_wrapper1(cell1);
    std::reference_wrapper<Cell> reference_wrapper2 = reference_wrapper1;
    std::cout << "reference_wrapper1: " << reference_wrapper1.get() << std::endl;
    std::cout << "reference_wrapper2: " << reference_wrapper2.get() << std::endl;

    cell1 = {1025, 1025};
    std::cout << "cell1: " << cell1 << std::endl;
    std::cout << "reference_wrapper1: " << reference_wrapper1 << std::endl;
    std::cout << "reference_wrapper2: " << reference_wrapper2 << std::endl;

    return 0;
}

输出

cell1: {1024,1024}
reference_wrapper1: {1024,1024}
reference_wrapper2: {1024,1024}
cell1: {1025,1025}
reference_wrapper1: {1025,1025}
reference_wrapper2: {1025,1025}


调用其所存储的函数

std::reference_wrapper<T>::operator()
template< class... ArgTypes >

typename std::result_of<T&(ArgTypes&&...)>::type

    operator() ( ArgTypes&&... args ) const;
(C++11 起)
(C++17 前)
template< class... ArgTypes >

std::invoke_result_t<T&, ArgTypes...>

    operator() ( ArgTypes&&... args ) const;
(C++17 起)

调用存储其引用的可调用 (Callable) 对象。仅若存储的引用指向可调用 (Callable) 对象,此函数才可用。

T 必须是完整类型。

参数

args-传递给被调用函数的参数

返回值

被调用函数的返回值。

异常

(无)

调用示例

#include <algorithm>
#include <list>
#include <vector>
#include <iostream>
#include <numeric>
#include <random>
#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;
    }

    Cell &operator*=(int n)
    {
        x *= n;
        y *= n;
        return *this;
    }

    Cell &operator++()
    {
        x += 1;
        y += 1;
        return *this;
    }
};

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

void Function1()
{
    std::cout << __FUNCTION__ << "  " << Cell{1024, 1024} << std::endl;
}

void Function2(Cell cell1)
{
    std::cout << __FUNCTION__ << "  " << cell1 + Cell{1024, 1024} << std::endl;
}

int main()
{
    std::reference_wrapper<void()> reference_wrapper1 = std::ref(Function1);
    reference_wrapper1();

    auto function2 = std::bind(Function2, std::placeholders::_1);
    auto reference_wrapper2 = std::ref(function2);
    reference_wrapper2(Cell{1024, 1024});

    auto function3 = []()
    {
        std::cout << "lambda function called" << std::endl;
    };
    auto reference_wrapper3 = std::ref(function3);
    reference_wrapper3();

    return 0;
}

输出

Function1  {1024,1024}
Function2  {2048,2048}
lambda function called

std::reference_wrapper 的推导指引

template<typename T>
reference_wrapper(T&) -> reference_wrapper<T>;

(C++17 起)

为 std::reference_wrapper 提供推导指引以支持单独类模板形参的推导。

  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值