我想拥有
template <class T>
void foo(T &t);
也能够接受临时对象,而不会影响通过引用接受其他对象并在它们上调用非常量方法。在 C++03 中可能吗?
我意识到我可能会强制用户将其对象的所有方法声明为const
,并将所有成员声明为mutable
,然后使用const T &t
引用,但这是一个丑陋的解决方法。
我想拥有
template <class T>
void foo(T &t);
也能够接受临时对象,而不会影响通过引用接受其他对象并在它们上调用非常量方法。在 C++03 中可能吗?
我意识到我可能会强制用户将其对象的所有方法声明为const
,并将所有成员声明为mutable
,然后使用const T &t
引用,但这是一个丑陋的解决方法。
在 C++03 中,无法推断传递给函数的参数是左值还是右值。
我想这就是为什么您的问题标题显示“按值接受临时变量”的原因:如果存在这样的机制,您可以创建一个函数(模板),根据该信息确定参数类型是否应该是T&
or 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
成员函数)不是一种解决方法(甚至不是一个丑陋的解决方法):如果成员函数是 all const
,则意味着foo()
不需要更改其输入的状态。这反过来意味着它可能需要一个const&
, 并且问题解决了。
您可能打算让这些const
成员函数执行 aconst_cast<>
以更改对象的状态,但是您也可以在foo()
. 这是一个坏主意的原因是,在这两种情况下,您都不能向foo()
类型为const
-qualified 的对象提供输入,并且您可能不知道是否是这种情况。
您可以创建第二个函数,该函数采用 const 类型引用,并为非常量类型引用制作副本。
template <class T>
void foo (T &t);
template <class T>
void foo (const T &x) {
T copy(x);
foo(copy);
}
可以在此处找到演示。
这种技术的局限性在于它不能区分临时对象和真实const
对象。这样做的结果是您的原件foo()
将不允许自己被传递一个const
对象。该提议将允许它们,因此您失去了最初提供的一些安全性。您可以通过将 const 类型版本重命名为foo
类似foo_for_temp
. 然后,调用者就会知道函数的意图。
一种但危险的解决方案是将 const T & 作为函数参数,然后将 const_cast<> 传递给 T&。您必须小心传递给函数的内容,因为它很容易导致未定义的行为:
template <class T>
void foo(const T &ct)
{
T &t = const_cast<T>( ct );
// ...
}