模板功能通过引用接受临时值和非临时值?

时间:2013-03-14 16:56:48

标签: c++ templates pass-by-reference c++03

我想

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

能够接受临时对象,同时不会因为通过引用接受其他对象并在其上调用非const方法而妥协。在C ++ 03中可能吗?

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

3 个答案:

答案 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 );
    // ...
}