关于std::follow

ID870177103 2016-04-29 04:07:10
	// TEMPLATE FUNCTION forward
template<class _Ty> inline
_CONST_FUN _Ty&& forward(
typename remove_reference<_Ty>::type& _Arg) _NOEXCEPT
{ // forward an lvalue as either an lvalue or an rvalue
return (static_cast<_Ty&&>(_Arg));
}

template<class _Ty> inline
_CONST_FUN _Ty&& forward(
typename remove_reference<_Ty>::type&& _Arg) _NOEXCEPT
{ // forward an rvalue as an rvalue
static_assert(!is_lvalue_reference<_Ty>::value, "bad forward call");
return (static_cast<_Ty&&>(_Arg));
}

为什么follow不允许使用左值参数?
在使用一些c语言编写的函数时候总会有这样的函数
int write (const char *str ,int *len) ;
第二个参数既要作为str长度的输入,又作为实际写入的字符数的返回,但是其实我并不关心这个返回值
我想用一个右值作为参数write ("123" ,&int (3)) ;
template <class T>
inline constexpr typename std::remove_reference<T>::type &delivers (T &&arg) {
return arg ;
}

显然右值不能取地址,但是write ("123",&std::delivers<int> (3)) ;这写法能通过
但是type_traits没有类似的函数
刚刚我突然觉得其实write ("123",&std::follow<int &> (3)) ;应该能和上面一样
却被这句阻止了static_assert(!is_lvalue_reference<_Ty>::value, "bad forward call");
有没有办法能在不修改库文件的情况下不触发那条断言
比如给follow加个偏特化之类的(可以就好了)
...全文
141 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
ri_aje 2016-04-30
  • 打赏
  • 举报
回复
引用 8 楼 ID870177103 的回复:
[quote=引用 6 楼 ri_aje 的回复:] c++ 不允许对左值取地址。 forward<int&> 的用法,进入第二个重载,要求不能是右值,所以没法用。 deliver<int> 只是强行把右值转换为左值了,绕过了语法检查系统,但最终取地址的对象仍然本身是个右值,会在表达式结束部分消失。楼主说本来也不关心写入的长度,貌似右值消失就消失了,但这种玩法还是很容易不小心进入未定义行为的领域,不推荐。 归根结底还是这库设计的有问题,不用返回值表示写入数,非得用参数。 [quote=引用 楼主 ID870177103 的回复:] int write (const char *str ,int *len) ; 第二个参数既要作为str长度的输入,又作为实际写入的字符数的返回,但是其实我并不关心这个返回值
这种情况你只能包装一下,比如这样。

int write (const char* str, int len)
{
 return write(str,&len);
}
[/quote] 的确这算是未定义行为,但编译器应该在语句结束后才析构掉右值吧 本来我就一直用的delivers,但如果能使用库函数的变种就不用每次写delivers了[/quote] 是的,语言要求临时变量在完整表达式末尾逆序析构,问题是右值可能都不对应临时变量。 delivers 的那种写法,还不如简单封装一下呢,最起码写一次其他调用的地方看着都正常了。
ri_aje 2016-04-30
  • 打赏
  • 举报
回复
引用 9 楼 ID870177103 的回复:
这些库一开始就是用c写的,所以代码风格就只能是这样 我曾经试过用智能指针封装windows句柄,但后来发现代码膨胀可读性变差,还不如用常用的__try __finally
c++ 干类似事情很正常,也挺好用的,你说封装以后可读性差了,我只能说可能是你的设计有问题。
ID870177103 2016-04-30
  • 打赏
  • 举报
回复
这些库一开始就是用c写的,所以代码风格就只能是这样 我曾经试过用智能指针封装windows句柄,但后来发现代码膨胀可读性变差,还不如用常用的__try __finally
ID870177103 2016-04-30
  • 打赏
  • 举报
回复
引用 5 楼 lm_whales 的回复:
[quote=引用 3 楼 ID870177103 的回复:] [quote=引用 1 楼 lm_whales 的回复:] int write (const char *str ,int* len) ; 和C++ int write (const char *str ,int& len) ; 效果相当
调用的是别人的库(就比如windows的api很多都是这样的),头文件的声明就是指针,我不可能每个函数都改吧[/quote] 封装一下 把 int write (const char *str ,int* len) ; 封装成 int write (const char *str ,int& len) ; [/quote] 太麻烦,本来就是想不用多声明一个变量而已 int len =3 ; write ("123" ,&len) ;
ID870177103 2016-04-30
  • 打赏
  • 举报
回复
引用 6 楼 ri_aje 的回复:
c++ 不允许对左值取地址。 forward<int&> 的用法,进入第二个重载,要求不能是右值,所以没法用。 deliver<int> 只是强行把右值转换为左值了,绕过了语法检查系统,但最终取地址的对象仍然本身是个右值,会在表达式结束部分消失。楼主说本来也不关心写入的长度,貌似右值消失就消失了,但这种玩法还是很容易不小心进入未定义行为的领域,不推荐。 归根结底还是这库设计的有问题,不用返回值表示写入数,非得用参数。 [quote=引用 楼主 ID870177103 的回复:] int write (const char *str ,int *len) ; 第二个参数既要作为str长度的输入,又作为实际写入的字符数的返回,但是其实我并不关心这个返回值
这种情况你只能包装一下,比如这样。

int write (const char* str, int len)
{
 return write(str,&len);
}
[/quote] 的确这算是未定义行为,但编译器应该在语句结束后才析构掉右值吧 本来我就一直用的delivers,但如果能使用库函数的变种就不用每次写delivers了
ri_aje 2016-04-29
  • 打赏
  • 举报
回复
c++ 不允许对左值取地址。 forward<int&> 的用法,进入第二个重载,要求不能是右值,所以没法用。 deliver<int> 只是强行把右值转换为左值了,绕过了语法检查系统,但最终取地址的对象仍然本身是个右值,会在表达式结束部分消失。楼主说本来也不关心写入的长度,貌似右值消失就消失了,但这种玩法还是很容易不小心进入未定义行为的领域,不推荐。 归根结底还是这库设计的有问题,不用返回值表示写入数,非得用参数。
引用 楼主 ID870177103 的回复:
int write (const char *str ,int *len) ; 第二个参数既要作为str长度的输入,又作为实际写入的字符数的返回,但是其实我并不关心这个返回值
这种情况你只能包装一下,比如这样。

int write (const char* str, int len)
{
 return write(str,&len);
}
lm_whales 2016-04-29
  • 打赏
  • 举报
回复
引用 3 楼 ID870177103 的回复:
[quote=引用 1 楼 lm_whales 的回复:] int write (const char *str ,int* len) ; 和C++ int write (const char *str ,int& len) ; 效果相当
调用的是别人的库(就比如windows的api很多都是这样的),头文件的声明就是指针,我不可能每个函数都改吧[/quote] 封装一下 把 int write (const char *str ,int* len) ; 封装成 int write (const char *str ,int& len) ;
ID870177103 2016-04-29
  • 打赏
  • 举报
回复
引用 2 楼 yshuise 的回复:
左值能取地址,右值不能取地址。
在右值的存在周期内,右值就是左值
ID870177103 2016-04-29
  • 打赏
  • 举报
回复
引用 1 楼 lm_whales 的回复:
int write (const char *str ,int* len) ; 和C++ int write (const char *str ,int& len) ; 效果相当
调用的是别人的库(就比如windows的api很多都是这样的),头文件的声明就是指针,我不可能每个函数都改吧
yshuise 2016-04-29
  • 打赏
  • 举报
回复
左值能取地址,右值不能取地址。
lm_whales 2016-04-29
  • 打赏
  • 举报
回复
int write (const char *str ,int* len) ; 和C++ int write (const char *str ,int& len) ; 效果相当

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧