A proposal to add a reference wrapper to the standard library (revision 1) (original) (raw)

Document number: N1453=03-0036
Revises document number: N1436=03-0018
Date: 9 April 2003
Project: Programming Language C++, Library Working Group
Reply-to: Doug Gregor <gregod@cs.rpi.edu>

Introduction

This proposal defines a small library addition for passing references to function templates (algorithms) that would usually take copies of their arguments. It defines the class templatereference_wrapper and the two functions ref andcref that return instances of reference_wrapper.

reference_wrapper is a CopyConstructible and Assignable wrapper around a reference to an object of typeT. It provides an implicit conversion toT&, often allowing the function templates to work on references unmodified. Some library components that would not work on references unmodified may instead detectreference_wrapper and alter their semantics accordingly, e.g., those in the Tuple and Function Object Wrapper proposals.

This proposal is based on the Boost.Ref library.

Usage Examples

reference_wrapper can be used in places where argument deduction would not deduce a reference, e.g., when forwarding arguments:

void f(int & r) { ++r; }

template<class F, class T> void g(F f, T t) { f(t); }

int main() { int i = 0; g(f, i); cout << i << endl; // 0 g(f, ref(i)); cout << i << endl; // 1 }

In particular, this can be used to overcome the limitations of forwarding constructor arguments:

struct X { explicit X(int & r); };

template struct wrapper { T t; template explicit wrapper(A1 const & a1): t(a1) {} };

int i = 0; wrapper w1(i); // error wrapper w1(ref(i)); // OK

More information on the forwarding problem is given in N1385.

reference_wrapper can be used where ordinary references cannot, e.g., in containers and (by way of implicit conversion) function calls that expect the underlying type.

std::list numbers; std::vector<reference_wrapper > number_refs; for(int i = 0; i < 100; ++i) { numbers.push_back(4ii^2 - 10*i + 3); number_refs.push_back(ref(numbers.back())); }

std::sort(number_refs.begin(), number_refs.end());

Additional examples are given in the Tuple and Function Object Wrapper proposals.

reference_wrapper contains an overloaded function call operator to enable passing function object references to standard algorithms. This capability is particularly useful for passing function objects that cannot be copied or stateful function objects:

struct counting_less { typedef bool result_type;

template bool operator()(const T& x, const T& y) { ++count; return x < y; }

int count; };

// ...

vector elements; // fill elements counting_less cl; sort(elements.begin(), elements.end(), ref(cl)); std::cout << cl.count << " comparisons in sort\n";

Impact on the standard

This proposal defines a pure library extension. . A new class template reference_wrapper is proposed to be added to the standard header with two supporting functions.

Proposed Text

namespace std { ��template<**typename** T> class reference_wrapper; ��template<**typename** T> ref(T&); ��template<**typename** T> cref(const T&); }

Class template reference_wrapper

std::reference_wrapper — Contains a reference to an object of type T.

Synopsis

template<typename** T> class reference_wrapper { public: ��_// types_ ��typedef** T type;

��_// construct/copy/destruct_ ��explicit reference_wrapper(T&);

��_// access_ ��operator () const; ��get() const;

��_// invocation_ ��template<typename** T1, typename T2, ..., typename TN> ����typename** result_of<T(T1, T2, ..., TN)>::type operator()(T1, T2, ..., TN) const; };

// constructors template<**typename** T> ref(T&); template<**typename** T> cref(const T&);

Description

reference_wrapper is a CopyConstructible and Assignable wrapper around a reference to an object of type T.

reference_wrapper defines the member typeresult_type in the following cases:

  1. T is a function pointer, then result_type is the return type of T.
  2. T is a pointer to member function, then result_type is the return type of T.
  3. T is a class type with a member type result_type, then result_type is T::result_type.

reference_wrapper construct/copy/destruct

  1. explicit reference_wrapper(T& t);
    Effects: Constructs areference_wrapper object that stores a reference tot.
    Throws: Does not throw.

reference_wrapper access

  1. operator () const;
    Returns: The stored reference.
    Throws: Does not throw.
  2. get() const;
    Returns: The stored reference.
    Throws: Does not throw.

reference_wrapper invocation

  1. template<typename** T1, typename T2, ..., typename TN>
    ��
    typename** result_of<T(T1, T2, ..., TN)>::type operator()(T1 a1, T2 a1, ... ,
    ����������������������������������������������������������TN aN) const;
    Effects:f.get()(a1, a2, ..., aN)
    Returns: The result of the expression f.get()(a1, a2, ..., aN)

reference_wrapper constructors

  1. template<**typename** T> ref(T& t);
    Returns:reference_wrapper(t)
    Throws: Does not throw.
  2. template<**typename** T> cref(const T& t);
    Returns:reference_wrapper(t)
    Throws: Does not throw.

Additions to "Implemention Quantities"

Maximum number of arguments forwarded by reference_wrapper [10]

Relationship with other proposals

Class template reference_wrapper and function templates ref and cref were also defined in documents N1402 (Function object wrappers) and N1403 (Tuples). The definition in this proposal is compatible with the definitions in both these proposals; this proposal is meant only to clarify the role of reference_wrapper and its helper functions, as requested by the committee.

Acknowledgements

Much of the text of this proposal comes from the Boost.Ref library documentation written by Peter Dimov. The first two examples were presented by Peter Dimov inc++std-ext-5635.

References

  1. J�rvi, Jaakko. Proposal for adding tuple types into the standard library. http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1403.pdf
  2. Gregor, Doug. A Proposal to add a Polymorphic Function Object Wrapper to the Standard Library. http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1402.html
  3. Dimov, Peter. The Forwarding Problem: Arguments. http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm
  4. The Boost.Ref Library. http://www.boost.org/libs/bind/ref.html