diff options
author | Douglas Gregor <doug.gregor@gmail.com> | 2008-10-18 23:02:17 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2008-10-18 23:02:17 +0000 |
commit | c393ec5a87f11010629763aa1cc34e1803642633 (patch) | |
tree | ff25247aece9e9b8e144f8ebe19cfb4acc03bbf2 | |
parent | 3cdf0c6237613202df8fa9f7e27bec61178122d5 (diff) | |
download | gcc-c393ec5a87f11010629763aa1cc34e1803642633.tar.gz |
stl_pair.h (__may_be_null_pointer_init): New.
2008-10-18 Douglas Gregor <doug.gregor@gmail.com>
* include/bits/stl_pair.h (__may_be_null_pointer_init): New.
(pair::pair): Eliminate the redundant pair(U1&&, U2&&) constructor.
Add lvalue pair<U1, U2> constructor to handle non-const pair lvalues.
Remove the old variadic constructor, and instead provide several
variadic constructors that avoid failing when attempting to
initialize a pointer from a null pointer constant.
* testsuite/20_util/pair/moveable.cc (test3): Add new tests with
initialization of pointers from the null pointer constant.
From-SVN: r141214
-rw-r--r-- | libstdc++-v3/ChangeLog | 11 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_pair.h | 91 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/pair/moveable.cc | 45 |
3 files changed, 138 insertions, 9 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 18aa1778d5e..cbbc0efe652 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2008-10-18 Douglas Gregor <doug.gregor@gmail.com> + + * include/bits/stl_pair.h (__may_be_null_pointer_init): New. + (pair::pair): Eliminate the redundant pair(U1&&, U2&&) constructor. + Add lvalue pair<U1, U2> constructor to handle non-const pair lvalues. + Remove the old variadic constructor, and instead provide several + variadic constructors that avoid failing when attempting to + initialize a pointer from a null pointer constant. + * testsuite/20_util/pair/moveable.cc (test3): Add new tests with + initialization of pointers from the null pointer constant. + 2008-10-17 Paolo Carlini <paolo.carlini@oracle.com> * include/bits/forward_list.tcc (forward_list<>:: diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index cf61b09945a..c169275ece3 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -65,8 +65,35 @@ #include <bits/move.h> // for std::move / std::forward, std::decay, and // std::swap +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#include <type_traits> +#endif + _GLIBCXX_BEGIN_NAMESPACE(std) +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +// A trait that determines whether the initialization of a T from +// arguments of type Args could possibly be the initialization of a +// pointer from a null pointer constant. +template<typename, typename...> +struct __may_be_null_pointer_init + : public false_type { }; + +template<typename _Tp, typename _Up> +struct __may_be_null_pointer_init<_Tp*, _Up> + : public integral_constant<bool, + (is_integral<typename remove_reference<_Up>::type>::value + || is_enum<typename remove_reference<_Up>::type>::value)> + { }; + +template<typename _Class, typename _Tp, typename _Up> +struct __may_be_null_pointer_init<_Tp _Class::*, _Up> + : public integral_constant<bool, + (is_integral<typename remove_reference<_Up>::type>::value + || is_enum<typename remove_reference<_Up>::type>::value)> + { }; +#endif + /// pair holds two objects of arbitrary type. template<class _T1, class _T2> struct pair @@ -89,10 +116,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std) : first(__a), second(__b) { } #ifdef __GXX_EXPERIMENTAL_CXX0X__ - template<class _U1, class _U2> - pair(_U1&& __x, _U2&& __y) - : first(std::forward<_U1>(__x)), - second(std::forward<_U2>(__y)) { } + // Omitted the following constructor, which appears in the C++0x + // working paper but is redundant with the variadic constructors + // below. + // + // template<class _U1, class _U2> + // pair(_U1&& __x, _U2&& __y); pair(pair&& __p) : first(std::move(__p.first)), @@ -111,12 +140,56 @@ _GLIBCXX_BEGIN_NAMESPACE(std) : first(std::move(__p.first)), second(std::move(__p.second)) { } - // http://gcc.gnu.org/ml/libstdc++/2007-08/msg00052.html - template<class _U1, class _Arg0, class... _Args> - pair(_U1&& __x, _Arg0&& __arg0, _Args&&... __args) + // This constructor is required so that lvalue pairs don't get + // pushed to the variadic constructor below. + template<class _U1, class _U2> + pair(pair<_U1, _U2>& __p) + : first(const_cast<const pair<_U1, _U2>&>(__p).first), + second(const_cast<const pair<_U1, _U2>&>(__p).second) { } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 811. pair of pointers no longer works with literal 0 + + // Variadic constructor. The enable_if makes sure that we won't + // try to initialize a pointer from an integral type, which + // needs to be handled by a different constructor that will + // convert a null pointer constant to that pointer type. See + // library issue 767. + template<class _U1, class... _Args, + class _Checker + = typename enable_if< + (!__may_be_null_pointer_init<_T1, _U1>::value + && !__may_be_null_pointer_init<_T2, _Args...>::value), + void>::type> + pair(_U1&& __x, _Args&&... __args) + : first(std::forward<_U1>(__x)), + second(std::forward<_Args>(__args)...) { } + + // Variadic constructor. The enable_if makes sure that the + // second argument isn't going to try to initialize a pointer + // from an integral type. However, T1 may be a pointer whose + // argument was a null pointer constant. + template<class... _Args, + class _Checker + = typename enable_if< + !__may_be_null_pointer_init<_T2, _Args...>::value, + void>::type> + pair(const _T1& __x, _Args&&... __args) + : first(__x), + second(std::forward<_Args>(__args)...) { } + + // Constructor typically used when T2 is a pointer and the + // second argument was a null pointer constant. The enable_if + // makes sure that the first argument isn't going to try to + // initialize a pointer from an integral type. + template<class _U1, + class _Checker + = typename enable_if< + !__may_be_null_pointer_init<_T1, _U1>::value, + void>::type> + pair(_U1&& __x, const _T2& __y) : first(std::forward<_U1>(__x)), - second(std::forward<_Arg0>(__arg0), - std::forward<_Args>(__args)...) { } + second(__y) { } pair& operator=(pair&& __p) diff --git a/libstdc++-v3/testsuite/20_util/pair/moveable.cc b/libstdc++-v3/testsuite/20_util/pair/moveable.cc index cd5de4162eb..4e5c53583cd 100644 --- a/libstdc++-v3/testsuite/20_util/pair/moveable.cc +++ b/libstdc++-v3/testsuite/20_util/pair/moveable.cc @@ -64,9 +64,54 @@ test2() r.second.size() == 2 && p.second.size() == 0); } +struct X { + explicit X(int, int) { } + +private: + X(const X&) = delete; +}; + +struct move_only { + move_only() { } + move_only(move_only&&) { } + +private: + move_only(const move_only&) = delete; +}; + +void +test3() +{ + int *ip = 0; + int X::*mp = 0; + std::pair<int*, int*> p1(0, 0); + std::pair<int*, int*> p2(ip, 0); + std::pair<int*, int*> p3(0, ip); + std::pair<int*, int*> p4(ip, ip); + + std::pair<int X::*, int*> p5(0, 0); + std::pair<int X::*, int X::*> p6(mp, 0); + std::pair<int X::*, int X::*> p7(0, mp); + std::pair<int X::*, int X::*> p8(mp, mp); + + std::pair<int*, X> p9(0, 1, 2); + std::pair<int X::*, X> p10(0, 1, 2); + std::pair<int*, X> p11(ip, 1, 2); + std::pair<int X::*, X> p12(mp, 1, 2); + + std::pair<int*, move_only> p13(0); + std::pair<int X::*, move_only> p14(0); + + std::pair<int*, move_only> p15(0, move_only()); + std::pair<int X::*, move_only> p16(0, move_only()); + std::pair<move_only, int*> p17(move_only(), 0); + std::pair<move_only, int X::*> p18(move_only(), 0); +} + int main() { test1(); test2(); + test3(); } |