我有下面这段代码,作为一个例子,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;
}
问题在于,对于我想使用dec_proxy的各种类型,我目前需要创建一个专门的dec_proxy实例 - 这似乎是一种非常混乱和有限的方法。
我的问题是:传递如此短暂的临时参数作为非const参考参数的正确方法是什么?
答案 0 :(得分:12)
根据Stephen的建议,您应该查看How come a non-const reference cannot bind to a temporary object?的答案,然后添加一个返回引用dec_proxy
的成员函数,例如:
dec_proxy &ref() { return *this; }
并致电foo
:
foo(
dec_proxy<int>(i).ref(),
dec_proxy<double>(j).ref(),
dec_proxy<short>(k).ref());
我很确定编译。
答案 1 :(得分:7)
感谢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中的参数有效。
答案 2 :(得分:2)
您尝试做的是将左值(您的new dec_facade<int>(i)
)作为左值参考传递,这解释了为什么它不起作用。
如果您的编译器支持它,您可以使用&&
类型修饰符来使用右值引用:
(可以通过打开C ++ 0x或C ++ 11 [partial]支持来启用对rvalue引用的支持)
template<typename T>
void foo(T& t)
{
++t;
}
template<typename T>
void foo(T&& t)
{
++t;
}
但这只是问题的一部分。你试图做的是预先增加一个临时值!这是无意义的,因为它不会在那个电话之后生活。你的物体会增量,然后被摧毁。
另一个解决方案是从函数定义中删除&
,这将允许它接受任何参数。但那可能不是你想要的。