(C++模板编程):std::declval(下)

目录

std::declval

返回左值引用还是返回右值引用

调用引用限定符修饰的成员函数范例

推导函数返回值范例

std::declval

返回左值引用还是返回右值引用

class A
{
public:
	A(int i) //构造函数
	{
		printf("A::A()函数执行了,this=%p\n", this);
	}

	double myfunc() //普通成员函数
	{
		printf("A::myfunc()函数执行了,this=%p\n", this);
		return 12.1;
	}

private:
	~A() {}
};

template <typename T>
T& mydeclval() noexcept;
  • 调用
using boost::typeindex::type_id_with_cvr;
cout << "decltype(mydeclval<A>)())的返回类型=" << type_id_with_cvr<decltype(mydeclval<A>())>().pretty_name() << endl;
cout << "decltype(mydeclval<A&>)())的返回类型=" << type_id_with_cvr<decltype(mydeclval<A&>())>().pretty_name() << endl;
cout << "decltype(mydeclval<A&&>)())的返回类型=" << type_id_with_cvr<decltype(mydeclval<A&&>())>().pretty_name() << endl;
  • 输出(用到了引用折叠)
decltype(mydeclval<A>)())的返回类型 = class A &
decltype(mydeclval<A&>)())的返回类型 = class A &
decltype(mydeclval<A&&>)())的返回类型 = class A &

将mydeclval返回改成右值引用

template <typename T>
T&& mydeclval() noexcept;
  • 输出(用到了引用折叠)
decltype(mydeclval<A>)())的返回类型 = class A &&
decltype(mydeclval<A&>)())的返回类型 = class A &
decltype(mydeclval<A&&>)())的返回类型 = class A &&
  • 通过上面两种方式对比可知:设定返回为右值引用,可以获得更多的类型,而设定返回左值应用不论传入什么类型的参数,返回全部的都是左值引用。

调用引用限定符修饰的成员函数范例

class ALR
{
public:
	void onAnyValue()
	{
		cout << "ALR::onAnyValue()函数执行了!" << endl;
	}

	void onLvalue()& //只能被类ALR的左值对象调用
	{
		cout << "ALR::onLvalue()函数执行了!" << endl;
	}

	void onRvalue()&& //只能被类ALR的右值对象调用
	{
		cout << "ALR::onRvalue()函数执行了!" << endl;
	}
};

template <typename T>
T&& mydeclval() noexcept;
  • 调用1
ALR alr;  //左值对象alr
alr.onLvalue();
//alr.onRvalue(); //编译错误,因为onRvalue只能被类A的右值对象调用
ALR().onRvalue();  //临时对象是右值对象
//ALR().onLvalue();  //编译错误,因为onLvalue只能被类A的左值对象调用
  • 调用2
decltype(mydeclval<ALR>().onAnyValue()); 
decltype(mydeclval<ALR&>().onLvalue()); //返回的 类型是class ALR &,代表返回的是左值对象,左值对象调用onLvalue没问题
decltype(mydeclval<ALR&&>().onRvalue()); //返回的 类型是class ALR &&,代表返回的是右值对象,右值对象调用onRvalue没问题
//decltype(mydeclval<ALR&>().onRvalue());//返回的 类型是class ALR &,代表返回的是左值对象,左值对象调用onRvalue是错误的
//decltype(mydeclval<ALR&&>().onLvalue()); //返回的 类型是class ALR &&,代表返回的是右值对象,右值对象调用onLvalue是错误的

将mydeclval返回改成左值引用

template <typename T>
T&& mydeclval() noexcept;
  • 调用
decltype(mydeclval<ALR>().onAnyValue());
decltype(mydeclval<ALR&>().onLvalue()); //返回的 类型是class ALR &,代表返回的是左值对象,左值对象调用onLvalue没问题
//decltype(mydeclval<ALR&&>().onRvalue()); //返回的 类型是class ALR &,代表返回的是左值对象,左值对象调用onRvalue是错误的
//decltype(mydeclval<ALR&>().onRvalue());//返回的 类型是class ALR &,代表返回的是左值对象,左值对象调用onRvalue是错误的
decltype(mydeclval<ALR&&>().onLvalue()); //返回的 类型是class ALR &,代表返回的是左值对象,左值对象调用onLvalue没问题

推导函数返回值范例

int myfunc(int a, int b) //函数类型一般是由函数的返回值和参数类型决定,与函数名没有关系,所以myfunc代表的函数类型是: int(int,int);
{
	return a + b;
}

template<typename T_F, typename... U_Args>
decltype(std::declval<T_F>()   (std::declval<U_Args>()...)) TestFnRtnImpl(T_F func, U_Args... args)
{
	auto rtnvalue = func(args...);
	return rtnvalue;
}
  • T_F:是int (*)(int,int)类型,也就是函数指针类型
  • decltype(std::declval<T_F>()   (std::declval<U_Args>()...)):是int类型,也就是myfunc函数的返回类型
    • a)decltype(std::declval<T_F>() ):是 int (* && )(int,int),函数指针的右值引用类型,其实就简单理解成函数指针类型
int (*fp_var)(int x, int y); //函数指针类型fp_var = int(*)(int,int)

int (* &&yy_fp_var)(int x, int y) = std::move(fp_var); //函数指针的右值引用yy_fp_var = int(* &&)(int,int),现在yy_fp_var就可以代表fp_var

fp_var = _nmsp2::myfunc;
cout << fp_var(1, 2) << endl;  //3
cout << yy_fp_var(1, 2) << endl; //3
  • b)decltype(std::declval<U_Args>()...)这种写法:推导出来的是两个int &&
  • 返回值推导若写成:decltype(T_F(U_Args...)) TestFnRtnImpl(T_F func, U_Args... args)
    • 报错:decltype不是这么用的,decltype后面圆括号中出现的一般都是变量、对象、表达式、函数名、函数指针名等等
  • 调用
uto result = TestFnRtnImpl(myfunc, 5, 8); //T_F被推断出 int(*)(int,int)

//或者指定T_F类型
auto result1 = TestFnRtnImpl<int(int,int)>(myfunc, 5, 8);

cout << result << endl;   //13

auto + decltype 后置语法方式

template<typename T_F, typename... U_Args>
auto TestFnRtnImpl2(T_F func, U_Args... args)->decltype(func(args...)) //decltype(func(args...)):int类型,也就是myfunc的返回类型。
//decltype(func):int(*)(int,int)类型,函数指针类型
{
	auto rtnvalue = func(args...);
	return rtnvalue;
}
  • 调用
auto result2 = TestFnRtnImpl2(myfunc, 13, 15);
cout << result2 << endl; //28

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值