std::pair of references
No, you cannot do this reliably in C++03, because the constructor of pair
takes references to T
, and creating a reference to a reference is not legal in C++03.
Notice that I said "reliably". Some common compilers still in use (for GCC, I tested GCC4.1, @Charles reported GCC4.4.4) do not allow forming a reference to a reference, but more recently do allow it as they implement reference collapsing (T&
is T
if T
is a reference type). If your code uses such things, you cannot rely on it to work on other compilers until you try it and see.
It sounds like you want to use boost::tuple<>
int a, b;
// on the fly
boost::tie(a, b) = std::make_pair(1, 2);
// as variable
boost::tuple<int&, int&> t = boost::tie(a, b);
t.get<0>() = 1;
t.get<1>() = 2;
Are the values stored in std::pair by reference or by value?
A std::pair
, in your specific case, is nothing more than, in so many words:
struct pair {
int first;
int second;
};
first
and second
, in your std::pair
, are non-reference class members. The full definition of std::pair
is pretty much
template<typename T1, typename T2> struct pair {
T1 first;
T2 second;
};
How can I have a pair with reference inside vector?
Since C++14 std::make_pair
is defined as
template< class T1, class T2 >
std::pair<V1,V2> make_pair( T1&& t, T2&& u );
where V1
and V2
are std::decay<T1>::type
and std::decay<T2>::type
respectively.
This means that your make_pair<const int&, int>
calls do not really produce pairs with references as their first elements (contrary to what you apparently believed). They actually produce temporaries of pair<int, int>
type. At this point you lose any attachment to the original int
object stored in your unique_ptr
.
When you pass these pair<int, int>
temporaries to push_back
, they get implicitly converted to temporaries of pair<const int&, int>
type, which is your vector's element type. Through this mechanism you attach references inside your vector's element to int
members of those pair<int, int>
temporaries produced by make_pair
(not to int
objects stored in your unique_ptr
s). Once the temporaries expire, the references go sour.
In this case you can eliminate this specific problem by avoiding make_pair
altogether and simply directly constructing std::pair
objects of proper type, e.g.
vector.push_back(std::pair<const int&, int>(*ptr, 11));
but you might run into other problems caused by raw references later.
How does this const reference for std::pair work?
When you do
const std::pair<key_type, T>& reference = *map_iterator;
*map_iterator
returns a std::pair<const key_type, T>&
. You then copy initialize a std::pair<key_type, T>
from that, and then you bind reference
to that temporary variable. Because you have a reference to const
, this will extend the lifetime of that temporary to be the lifetime of the reference and you now have an element that is a copy of the one from the map. Basically you've done
std::pair<key_type, T> copy = *map_iterator;
The above conversion sequence works because you are allowed up to one user defined conversion in initialization and the compiler will try to do that to give you a valid initialization.
read values of reference direct by std::pair std::array std::array u_int16_t,2 ,1 ,std::string
std::get
returns references. You can just store these references:
const auto& PosTextfield = std::get<0>(out);
const auto& val = std::get<1>(out);
or
const auto& PosTextfield = out.first;
const auto& val = out.second;
or you can replace the auto
keywords with the actual types if you prefer. const
can be removed as well, since auto
will deduce it, but writing it explicitly makes it clear to the reader that the two references are non-modifiable.
This doesn't create any new objects. The references refer to the elements of the pair passed to the function.
Or just refer to the element directly where you want to use them with out.first
and out.second
or std::get<0>(out)
and std::get<1>(out)
.
std::pair with reference to unique pointer
std::make_pair()
will automatically decay any references given to it to their value types.
The deduced types
V1
andV2
arestd::decay<T1>::type
andstd::decay<T2>::type
(the usual type transformations applied to arguments of functions passed by value) unless application ofstd::decay
results instd::reference_wrapper<X>
for some typeX
, in which case the deduced type isX&
.
https://en.cppreference.com/w/cpp/utility/pair/make_pair
Remove your explicit instantiation of the type parameters of std::make_pair()
and wrap the emplace_back()
call with std::ref
:
return std::make_pair(
std::move(panelID),
std::ref(panels.emplace_back())
);
Alternatively, you can explicitly make the std::pair
:
return std::pair<PanelID, Panel_Ptr&>(
std::move(panelID),
panels.emplace_back()
);
Finally, to note on your code, you are calling std::move()
on your PanelID
type even though it is just an integer. std::move()
is useless in that scenario, so removing it entirely would make your code clearer.
Though, putting the generation of panelID
on a separate statement is still necessary due to the unspecified order of evaluation of arguments passed to functions. Good awareness of this fact.
Why does std::make_pair return a pair of reference types
As far as I know make_pair
has the following prototype:
template<class Type1, class Type2>
std::pair<Type1,Type2> make_pair(Type1 first_value, Type2 second_value);
(Note: slightly different since C++11)
See also http://en.cppreference.com/w/cpp/utility/pair/make_pair.
This is also what the standard says in §20.3.3 [pairs.spec]
. So this must be an error in the book (or you may have overlooked something).
Related Topics
C++: Safe to Use Longjmp and Setjmp
How to Get the CPU Usage Per Thread on Windows (Win32)
Issue When Scheduling Tasks Using Clock() Function
Getdibits and Loop Through Pixels Using X, Y
Non-Class Rvalues Always Have Cv-Unqualified Types
What Kinds of Optimizations Does 'Volatile' Prevent in C++
Why Are Strings in C++ Usually Terminated with '\0'
Building and Accessing a List of Types at Compile Time
Why Does the Library Linker Flag Sometimes Have to Go at the End Using Gcc
How to Expand Call to Variadic Template Base Classes
How to Check Whether Two Matrices Are Identical in Opencv
How to Call MAChine Code Stored in Char Array
Parameter Pack Must Be at the End of the Parameter List... When and Why