我想
template <class T>
void foo(T &t);
能够接受临时对象,同时不会因为通过引用接受其他对象并在其上调用非const方法而妥协。在C ++ 03中可能吗?
我意识到我可能强迫用户将其对象的所有方法声明为const
,将所有成员声明为mutable
,然后使用const T &t
引用,但这是一个丑陋的解决方法
答案 0 :(得分:4)
在C ++ 03中,没有办法推断传递给函数的参数是左值还是左值。
我想这就是为什么你的问题的标题上写着“接受临时值”的原因:如果存在这样的机制,你可以创建一个函数(模板)来确定参数类型是否存在应该是T&
或T
,基于该信息。
这正是C ++ 11中支持的类型推导机制所做的:
template<typename T>
void foo(T&& t);
// ^^^
// lvalue of type A is passed: T = A&, signature = foo(A& t)
// rvalue of type A is passed: T = A, signature = foo(A&& t)
但如上所述,这在C ++ 03中是不可能的,因为它缺乏确定表达式的值类别的方法。
你提到的可能性(强制所有对象都有const
成员函数)不是一种解决方法(甚至不是一个丑陋的):如果成员函数都是const
,则意味着{{1不需要改变其输入的状态。这反过来意味着它可能需要foo()
,问题就解决了。
你可能想让那些const&
成员函数执行const
以改变对象的状态,但是你可以再次在const_cast<>
内部。这是一个坏主意的原因是,在这两种情况下,您都无法向foo()
输入一个类型为foo()
的对象 - 合格,您可能不知道这是否是案件。
答案 1 :(得分:1)
您可以创建第二个带有const类型引用的函数,并为非const类型引用创建一个副本。
template <class T>
void foo (T &t);
template <class T>
void foo (const T &x) {
T copy(x);
foo(copy);
}
可以找到演示here。
此技术的局限性在于它无法区分临时对象和真正的const
对象。这样做的结果是原始的foo()
将不允许自己传递const
个对象。这个提议允许他们,因此你失去了最初提供的安全性。您可以通过将foo
的const类型版本重新命名为foo_for_temp
来弥补这一点。然后,调用者将知道该函数的意图。
答案 2 :(得分:0)
一个但危险的解决办法是让const T&amp;作为函数参数然后const_cast&lt;&gt;它对T&amp ;.您必须小心传递给函数的内容,因为它很容易导致未定义的行为:
template <class T>
void foo(const T &ct)
{
T &t = const_cast<T>( ct );
// ...
}