3

我想拥有

template <class T>
void foo(T &t);

也能够接受临时对象,而不会影响通过引用接受其他对象并在它们上调用非常量方法。在 C++03 中可能吗?

我意识到我可能会强制用户将其对象的所有方法声明为const,并将所有成员声明为mutable,然后使用const T &t引用,但这是一个丑陋的解决方法。

4

3 回答 3

4

在 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 的对象提供输入,并且您可能不知道是否是这种情况。

于 2013-03-14T17:21:12.227 回答
1

您可以创建第二个函数,该函数采用 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. 然后,调用者就会知道函数的意图。

于 2013-03-14T17:19:17.210 回答
0

一种但危险的解决方案是将 const T & 作为函数参数,然后将 const_cast<> 传递给 T&。您必须小心传递给函数的内容,因为它很容易导致未定义的行为:

template <class T>
void foo(const T &ct)
{
    T &t = const_cast<T>( ct );
    // ...
}
于 2013-03-14T17:07:46.453 回答