Reedited: first of all, this is just a matter of curiosity, I do know, that std::pair or lots of other solutions could eradicate this issue.
Can you tell me, what is exactly behind of this following problem? This code is a simple example working on c++03 and fails on c++11.
std::pair<int*,int**> getsth(int* param)
{
return std::make_pair<int*,int**>(param, 0);
}
int main(int argc, char* argv[])
{
int* a = new int(1);
std::pair<int*,int**> par = getsth(a);
std::cout << *par.first;
return 0;
}
I do know how to fix it to be compatible with both standards here, but it is annyoing me, that I don't know, what is exactly behind make_pair in this case.
Thanks!
edited: a compile error message from Coliru:
main.cpp: In function 'std::pair<int*, int**> getsth(int*)':
main.cpp:8:47: error: no matching function for call to 'make_pair(int*&, int)'
return std::make_pair<int*,int**>(param, 0);
^
main.cpp:8:47: note: candidate is:
In file included from /usr/local/include/c++/4.9.2/bits/stl_algobase.h:64:0,
from /usr/local/include/c++/4.9.2/bits/char_traits.h:39,
from /usr/local/include/c++/4.9.2/ios:40,
from /usr/local/include/c++/4.9.2/ostream:38,
from /usr/local/include/c++/4.9.2/iostream:39,
from main.cpp:1:
/usr/local/include/c++/4.9.2/bits/stl_pair.h:276:5: note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_Tp>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
make_pair(_T1&& __x, _T2&& __y)
^
/usr/local/include/c++/4.9.2/bits/stl_pair.h:276:5: note: template argument deduction/substitution failed:
main.cpp:8:47: note: cannot convert 'param' (type 'int*') to type 'int*&&'
return std::make_pair<int*,int**>(param, 0);
^
main.cpp:9:1: warning: control reaches end of non-void function [-Wreturn-type]
}
Rvalue references happened. Where std::make_pair
in C++03 has the signature
template< class T1, class T2 >
std::pair<T1,T2> make_pair( T1 t, T2 u );
In C++11, it has
template< class T1, class T2 >
std::pair<V1,V2> make_pair( T1&& t, T2&& u );
V1
and V2
are (usually) std::decay<T1|T2>::type
. C++14 adds constexpr
, but that does concern us here.
This means that the explicit function template specialization std::make_pair<int*, int**>
accepted, in C++03, parameters of type int*
and int**
, while the new one in C++11 accepts int*&&
and int**&&
.
Binding 0
to int**&&
is not a problem, but param
is an lvalue and cannot be bound to an rvalue reference to int*
. And that is why your code explodes in C++11.
For this reason,
return std::make_pair<int*&, int**>(param, 0);
works with both C++03 and C++11 -- param
can be bound to int*&
, and the resulting std::pair<int*&, int**>
can be converted to the std::pair<int*, int**>
that the function wants to return in both revisions.
That is rather ugly, though, and std::make_pair
is not really meant to be used this way. As @T.C. points out in the comments, if you know the types the std::pair
should have, just use
return std::pair<int*, int**>(param, 0);
You need to remove the template parameters of make_pair. Here is more info on why.
Also, you should pass nullptr
to make_pair
, not 0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With