简体   繁体   中英

What does add_lvalue_reference do?

I have this class that makes a path for a montecarlo simulator where it takes creates paths of integers from an array of available ints. So for example we could have a path of length 3 drawn from the array containing {0,1,2,3,4} and this would for example generate 3,1,2 and 1,4,0.

//This path generator just generates a list of ints for each path
template< typename randgen >
class MCPathGen {
    public:
        typedef vector< int > mcpath_t;
        typedef randgen randgen_t;
        typedef typename add_lvalue_reference<randgen>::type randgen_ref_t;

        MCPathGend(randgen_ref_t r) : m_rgen(r) {}

        //generate a single path by shuffling a copy of blank_d
        mcpath_t operator()() {
            Chooser< randgen_t > choose(m_rgen);
            mcpath_t path_temp(blank_d.begin(), blank_d.end());
            random_shuffle(path_temp.begin(), path_temp.end(), choose);

            return path_temp;
        };

    private:
        randgen_ref_t m_rgen;

};

Now I'm not quite sure what my colleague has done by using typedef typename add_lvalue_reference<randgen>::type randgen_ref_t;

What does add_lvalue_reference do? Is this necessary for making the code work?

I have not seen this before, so any insight is appreciated!

Copying pseudo-random number generators means you'd get the same stream of "random" numbers from each, which is not desirable, so you need a reference there.

However, you could just say randgen& .

According to [dcl.ref] in draft 3225, just randgen& will create an lvalue reference no matter what's passed in (type, lvalue-reference-type, or rvalue-reference-type), so I'd just use that.

Quote from the standard that controls this behavior:

If a typedef (7.1.3), a type template-parameter (14.3.1), or a decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a type T , an attempt to create the type “lvalue reference to cv TR ” creates the type “lvalue reference to T ”, while an attempt to create the type “rvalue reference to cv TR ” creates the type TR .

[ Example:

int  i;
typedef  int&  LRI;
typedef  int&&  RRI;

LRI&  r1  =  i; // r1 has the type int&
const  LRI&  r2  =  i; // r2 has the type int&
const  LRI&&  r3  =  i; // r3 has the type int&

RRI&  r4  =  i; // r4 has the type int&
RRI&&  r5  =  i; // r5 has the type int&&

decltype(r2)&  r6  =  i; // r6 has the type int&
decltype(r2)&&  r7  =  i; // r7 has the type int&

— end example ]

From section [meta.trans.ref] :

template <class T> struct add_lvalue_reference; If T names an object or function type then the member typedef type shall name T& ; otherwise, if T names a type “rvalue reference to T1 ” then the member typedef type shall name T1& ; otherwise, type shall name T .

They are exactly the same thing.

In C++03, they're the same thing too. From [type.arg.type] :

If a template-argument for a template-parameter T names a type “reference to cv1 S ”, an attempt to create the type “reference to cv2 T ” creates the type “reference to cv12 S ”, where cv12 is the union of the cv-qualifiers cv1 and cv2 . Redundant cv-qualifiers are ignored.

[ Example:

template   < class  T >  class   X  {
void   f( const   T &);
/ ∗ . . . ∗ /
};
X< int & >  x;          / / X<int&>::f has the parameter type const  int&

— end example ]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM