Xan*_*lip 9 c++ proxy-classes facade pass-by-reference
我有下面这段代码,作为一个例子,dec_proxy尝试将增量运算符的效果反转到在复杂函数调用foo中执行的类型 - 顺便说一下我无法更改接口.
#include <iostream>
template<typename T>
class dec_proxy
{
public:
dec_proxy(T& t)
:t_(t)
{}
dec_proxy<T>& operator++()
{
--t_;
return *this;
}
private:
T& t_;
};
template<typename T, typename S, typename R>
void foo(T& t, S& s, R& r)
{
++t;
++s;
++r;
}
int main()
{
int i = 0;
double j = 0;
short k = 0;
dec_proxy<int> dp1(i);
dec_proxy<double> dp2(j);
dec_proxy<short> dp3(k);
foo(dp1,dp2,dp3);
//foo(dec_proxy<int>(i), <---- Gives an error
// dec_proxy<double>(j), <---- Gives an error
// dec_proxy<short>(k)); <---- Gives an error
std::cout << "i=" << i << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
问题是,对于我想使用dec_proxy的各种类型,我目前需要创建一个专门的dec_proxy实例 - 这似乎是一个非常混乱和有限的方法.
我的问题是:传递如此短暂的临时参数作为非const参考参数的正确方法是什么?
MSN*_*MSN 12
根据斯蒂芬的建议,你应该看一下非const引用如何不能绑定到临时对象的答案?并简单地添加一个返回引用的成员函数dec_proxy,例如:
dec_proxy &ref() { return *this; }
并致电foo:
foo(
dec_proxy<int>(i).ref(),
dec_proxy<double>(j).ref(),
dec_proxy<short>(k).ref());
Run Code Online (Sandbox Code Playgroud)
我很确定编译.
感谢MSN,解决方案:
我不认为添加功能模板是正确的template<typename T> dec_proxy_impl<T>& dec_proxy(T&t).
它做的只是欺骗编译器.这将导致运行时错误.该函数foo需要lvaue或左值引用.但是template<typename T> dec_proxy_impl<T>& dec_proxy(T&t)不返回有效的左值引用.在实现中,它创建一个临时对象,并返回它.函数调用完成后,临时对象将被销毁.所以传递给函数的值引用foo是错误的.实际上引用的对象已被破坏.在++t;++s;++r试图访问无效的对象.行为未定义.
MSN的解决方案是正确的.对象的生命周期dec_proxy<int>(i)是从它的声明到函数调用的结束.它确保函数foo中的参数有效.