Implement LWG 2488 - Make the placeholders constexpr.

This patch makes the bind placeholders in std::placeholders both (1) const and
(2) constexpr (See below).

This is technically a breaking change for any code using the placeholders
outside of std::bind and depending on them being non-const. However I don't
think this will break any real world code.

(1) Previously the placeholders were non-const extern globals in all
dialects. This patch changes these extern globals to be const in all dialects.
Since the cv-qualifiers don't participate in name mangling for globals this
is an ABI compatible change.

(2) Make the placeholders constexpr in C++11 and beyond. Although LWG 2488 only
applies to C++17 I don't see any reason not to backport this change.

llvm-svn: 273824
This commit is contained in:
Eric Fiselier 2016-06-26 21:01:34 +00:00
parent a9fb19d3a5
commit 555330719a
4 changed files with 63 additions and 21 deletions

View File

@ -1980,16 +1980,29 @@ namespace placeholders
template <int _Np> struct __ph {}; template <int _Np> struct __ph {};
_LIBCPP_FUNC_VIS extern __ph<1> _1; #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_BIND)
_LIBCPP_FUNC_VIS extern __ph<2> _2; _LIBCPP_FUNC_VIS extern const __ph<1> _1;
_LIBCPP_FUNC_VIS extern __ph<3> _3; _LIBCPP_FUNC_VIS extern const __ph<2> _2;
_LIBCPP_FUNC_VIS extern __ph<4> _4; _LIBCPP_FUNC_VIS extern const __ph<3> _3;
_LIBCPP_FUNC_VIS extern __ph<5> _5; _LIBCPP_FUNC_VIS extern const __ph<4> _4;
_LIBCPP_FUNC_VIS extern __ph<6> _6; _LIBCPP_FUNC_VIS extern const __ph<5> _5;
_LIBCPP_FUNC_VIS extern __ph<7> _7; _LIBCPP_FUNC_VIS extern const __ph<6> _6;
_LIBCPP_FUNC_VIS extern __ph<8> _8; _LIBCPP_FUNC_VIS extern const __ph<7> _7;
_LIBCPP_FUNC_VIS extern __ph<9> _9; _LIBCPP_FUNC_VIS extern const __ph<8> _8;
_LIBCPP_FUNC_VIS extern __ph<10> _10; _LIBCPP_FUNC_VIS extern const __ph<9> _9;
_LIBCPP_FUNC_VIS extern const __ph<10> _10;
#else
constexpr __ph<1> _1{};
constexpr __ph<2> _2{};
constexpr __ph<3> _3{};
constexpr __ph<4> _4{};
constexpr __ph<5> _5{};
constexpr __ph<6> _6{};
constexpr __ph<7> _7{};
constexpr __ph<8> _8{};
constexpr __ph<9> _9{};
constexpr __ph<10> _10{};
#endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_BIND)
} // placeholders } // placeholders

View File

@ -7,6 +7,7 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#define _LIBCPP_BUILDING_BIND
#include "functional" #include "functional"
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
@ -14,16 +15,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace placeholders namespace placeholders
{ {
__ph<1> _1; const __ph<1> _1{};
__ph<2> _2; const __ph<2> _2{};
__ph<3> _3; const __ph<3> _3{};
__ph<4> _4; const __ph<4> _4{};
__ph<5> _5; const __ph<5> _5{};
__ph<6> _6; const __ph<6> _6{};
__ph<7> _7; const __ph<7> _7{};
__ph<8> _8; const __ph<8> _8{};
__ph<9> _9; const __ph<9> _9{};
__ph<10> _10; const __ph<10> _10{};
} // placeholders } // placeholders

View File

@ -10,10 +10,14 @@
// <functional> // <functional>
// placeholders // placeholders
// The placeholders are constexpr in C++17 and beyond.
// libc++ provides constexpr placeholders in C++11 and beyond.
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>
#include "test_macros.h"
template <class T> template <class T>
void void
test(const T& t) test(const T& t)
@ -28,6 +32,30 @@ test(const T& t)
static_assert(std::is_nothrow_move_constructible<T>::value, ""); static_assert(std::is_nothrow_move_constructible<T>::value, "");
} }
#if TEST_STD_VER >= 11
constexpr decltype(std::placeholders::_1) default1{};
constexpr decltype(std::placeholders::_2) default2{};
constexpr decltype(std::placeholders::_3) default3{};
constexpr decltype(std::placeholders::_4) default4{};
constexpr decltype(std::placeholders::_5) default5{};
constexpr decltype(std::placeholders::_6) default6{};
constexpr decltype(std::placeholders::_7) default7{};
constexpr decltype(std::placeholders::_8) default8{};
constexpr decltype(std::placeholders::_9) default9{};
constexpr decltype(std::placeholders::_10) default10{};
constexpr decltype(std::placeholders::_1) cp1 = std::placeholders::_1;
constexpr decltype(std::placeholders::_2) cp2 = std::placeholders::_2;
constexpr decltype(std::placeholders::_3) cp3 = std::placeholders::_3;
constexpr decltype(std::placeholders::_4) cp4 = std::placeholders::_4;
constexpr decltype(std::placeholders::_5) cp5 = std::placeholders::_5;
constexpr decltype(std::placeholders::_6) cp6 = std::placeholders::_6;
constexpr decltype(std::placeholders::_7) cp7 = std::placeholders::_7;
constexpr decltype(std::placeholders::_8) cp8 = std::placeholders::_8;
constexpr decltype(std::placeholders::_9) cp9 = std::placeholders::_9;
constexpr decltype(std::placeholders::_10) cp10 = std::placeholders::_10;
#endif // TEST_STD_VER >= 11
int main() int main()
{ {
test(std::placeholders::_1); test(std::placeholders::_1);

View File

@ -161,7 +161,7 @@
<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2467">2467</td><td>is_always_equal has slightly inconsistent default</td><td>Lenexa</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2467">2467</td><td>is_always_equal has slightly inconsistent default</td><td>Lenexa</td><td>Complete</td></tr>
<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2470">2470</td><td>Allocator's destroy function should be allowed to fail to instantiate</td><td>Lenexa</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2470">2470</td><td>Allocator's destroy function should be allowed to fail to instantiate</td><td>Lenexa</td><td>Complete</td></tr>
<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2482">2482</td><td>[c.strings] Table 73 mentions nonexistent functions</td><td>Lenexa</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2482">2482</td><td>[c.strings] Table 73 mentions nonexistent functions</td><td>Lenexa</td><td>Complete</td></tr>
<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2488">2488</td><td>Placeholders should be allowed and encouraged to be constexpr</td><td>Lenexa</td><td></td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2488">2488</td><td>Placeholders should be allowed and encouraged to be constexpr</td><td>Lenexa</td><td>Complete</td></tr>
<tr><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td></tr>
<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#1169">1169</a></td><td><tt>num_get</tt> not fully compatible with <tt>strto*</tt></td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#1169">1169</a></td><td><tt>num_get</tt> not fully compatible with <tt>strto*</tt></td><td>Kona</td><td>Complete</td></tr>
<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2072">2072</a></td><td>Unclear wording about capacity of temporary buffers</td><td>Kona</td><td>Complete</td></tr> <tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2072">2072</a></td><td>Unclear wording about capacity of temporary buffers</td><td>Kona</td><td>Complete</td></tr>