Re: transform, make_pair, and rvalues
Am 12.04.2014 20:10, schrieb James K. Lowden:
Today we encountered an rvalue question I couldn't answer.
Array a;
Array64 b;
std::map<int, uint64_t> c;
transform( a.begin(), a.end(), b.begin(), inserter(c, c.begin()),
make_pair<int, uint64_t> );
The compilation error from VC11 said it couldn't convert parameter 2 of
make_pair from uint64_t&& to uint64_t. Bug or feature?
It depends on your position. According to the specification of C++11
std::make_pair your code is requesting an instantiation of
std::make_pair that accepts rvalues of it's arguments, just look at the
declaration:
template <class T1, class T2>
constexpr /see below/ make_pair(T1&&, T2&&);
Given your template arguments the required specialization is:
template <>
constexpr /see below/ make_pair(int&&, uint64_t&&);
Clearly this function only accepts rvalues of int and uint64_t.
The "Array" type is homegrown (as is its iterator), and there is no
method to provide a const_iterator. In point of fact the Array64 type
is based on a signed int64_t, but IMO that doesn't matter provided
the values are in [0, 2**63).
The hack today was to supply a static function to std::transform:
std::pair<int, uint64_t>
make_my_pair( int k, uint64_t v) {
return make_pair(k, v);
}
which is a little ... unsatisfying.
This is not the only possible choice you have. Instead you could change
the instantiation to your needs, e.g. to
make_pair<int&, uint64_t&>
or even more general
make_pair<const int&, const uint64_t&>
The advantage of the second form is that it does not depend on the
const-ness of the iterator type and will work for both mutable and
constant iterator types.
std::make_pair accepts as its second argument a reference or an rvalue
reference. As I understand the error, the compiler sees a (non-const)
iterator and attempts move semantics on the reference provided by
the iterator, where copy semantics are clearly required.
Your interprettaion is wrong. The problem is not related to the
const-ness of the iterator (or its lack of), but due to the requested
rvalue-character of the std::make_pair argument types.
What is the proper fix? ISTM the code is correct; calls to
std::transform are not required to provide constant iterators. Is the
iterator perhaps required to provide a trait to tell the compiler to
DTRT? Or can I tell Microsoft the error is bogus?
The compiler and the library are correct, just apply the simple fix as
suggested above.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]