C++ 新特性学习(五) — 引用包装、元编程的类型属性和计算函数对象返回类型

2023-03-05 14:30:38 浏览数 (1)

这各部分主要是一些很实用和在一些地方帮助编译器自动推断类型的库和函数 首先是引用包装 类名 template< class T > class std::reference_wrapper; 这个类保存了对一个类实例、(成员)函数(指针) 构造时必须传入所引用的对象或引用对象的右值引用 主要方法有 =号操作符, 用于重新绑定引用对象 类型转换操作符, 用于转换为模板目标类的引用类型 get方法, 用于获取引用的对象 ()操作符, 用于执行引用的函数

同时与其配对的函数有 std::ref 返回std::reference_wrapper,可以视为转换对象为引用 std::cref 返回常量引用对象std::reference_wrapper,可以视为转换对象为引用 例程:

代码语言:javascript复制
// 和std::function和std::bind函数配合使用
#include <cstdio>
#include <functional>

 void assign(int& l, int r) {
    l = r;
 }
int main() {
    int a = 0, b = 10;
    std::function<void()> func = std::bind(&assign, std::ref(a), b); 
    func();

    printf("a => %d, b => %dn", a, b);
    return 0;
}

注意:如果不用std::ref包装,即便函数申明需传入引用类型,但是由于绑定变量和函数的参数类型推断是分离的,会导致传值而不是引用 另外有些函数,如 std::ptr_fun, 通过函数指针构造函数对象 std::mem_fun, 通过成员函数指针构造函数对象 std::mem_fun_ref, 通过成员函数指针构造函数对象引用 不推荐使用,因为完全可以用std::bind代替,详细请参见 http://www.owent.net/2012/536.html

然后是 元编程的类型属性

元编程的定义是可以修改自身或其他代码的代码,当然,C 不是动态语言,这个修改可以在编译或执行的时期。 说不清楚,还是上代码吧

代码语言:javascript复制
#include <cstdio>

template <int N>
struct factorial {
    const static int value = N * factorial<N - 1>::value;
};

template <>
struct factorial<1> {
    const static int value = 1;
};

int main() {
    printf("10! = %dn", factorial<10>::value);
    return 0;
}

比较有意思吧,这个不是新标准,新C 标准增加了类型属性,什么叫类型属性呢? 就是类型判断,也来一个例子吧,这段代码来自维基百科

代码语言:javascript复制
#include <type_traits>
// 算法一
template< bool B > struct Algorithm {
    template<class T1, class T2> int do_it (T1 &, T2 &)  { /*...*/ }
};

// 算法二
template<> struct Algorithm<true> {
    template<class T1, class T2> int do_it (T1, T2)  { /*...*/ }
};

// 根据给定的类型选择不同的算法
template<class T1, class T2>
int elaborate (T1 A, T2 B)
{
    // 若 T1 为 int 且 T1 为 float,选用算法二
    // 其它情況选用算法一
    return Algorithm<std::is_integral<T1>::value && std::is_floating_point<T2>::value>::do_it( A, B ) ;
}

最后,是今天最后一项,计算函数对象(仿函数)的返回值类型 主要涉及一个模板函数std::result_of,它使用了decltype并支持函数对象(关于decltype请参见 https://www.owent.net/2011/508.html) std::result_of::type 即是返回类型,比如:

代码语言:javascript复制
struct foo {
    double operator()(char, int);
};
// 这两个是一样的
std::result_of<foo(char, int)>::type d1 = 10.0;
decltype(foo()('c', 1)) d2 = 10.0;

今天就这样over吧。也许是我还没能把C 用的非常灵活吧,感觉后面的部分不太实用的样子。 还需要继续努力啊

0 人点赞