Commit 38bda487 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

like, like_t, forward_like

Summary:
[Folly] `like`, `like_t`, `forward_like`, as per p0847r0.

See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0847r0.html.

Reviewed By: nbronson

Differential Revision: D8040722

fbshipit-source-id: 4c8a64037ec7447c8afa7b086c36db0f836f66f2
parent 1fe37d89
...@@ -167,6 +167,49 @@ struct remove_cvref { ...@@ -167,6 +167,49 @@ struct remove_cvref {
template <typename T> template <typename T>
using remove_cvref_t = typename remove_cvref<T>::type; using remove_cvref_t = typename remove_cvref<T>::type;
namespace detail {
template <typename Src>
struct like_ {
template <typename Dst>
using apply = Dst;
};
template <typename Src>
struct like_<Src const> {
template <typename Dst>
using apply = Dst const;
};
template <typename Src>
struct like_<Src volatile> {
template <typename Dst>
using apply = Dst volatile;
};
template <typename Src>
struct like_<Src const volatile> {
template <typename Dst>
using apply = Dst const volatile;
};
template <typename Src>
struct like_<Src&> {
template <typename Dst>
using apply = typename like_<Src>::template apply<Dst>&;
};
template <typename Src>
struct like_<Src&&> {
template <typename Dst>
using apply = typename like_<Src>::template apply<Dst>&&;
};
} // namespace detail
// mimic: like_t, p0847r0
template <typename Src, typename Dst>
using like_t = typename detail::like_<Src>::template apply<remove_cvref_t<Dst>>;
// mimic: like, p0847r0
template <typename Src, typename Dst>
struct like {
using type = like_t<Src, Dst>;
};
/** /**
* type_t * type_t
* *
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <utility> #include <utility>
#include <folly/CPortability.h> #include <folly/CPortability.h>
#include <folly/Traits.h>
namespace folly { namespace folly {
...@@ -101,6 +102,12 @@ void as_const(T const&&) = delete; ...@@ -101,6 +102,12 @@ void as_const(T const&&) = delete;
#endif #endif
// mimic: forward_like, p0847r0
template <typename Src, typename Dst>
constexpr like_t<Src, Dst>&& forward_like(Dst&& dst) noexcept {
return static_cast<like_t<Src, Dst>&&>(std::forward<Dst>(dst));
}
#if __cpp_lib_exchange_function || _LIBCPP_STD_VER > 11 || _MSC_VER #if __cpp_lib_exchange_function || _LIBCPP_STD_VER > 11 || _MSC_VER
/* using override */ using std::exchange; /* using override */ using std::exchange;
......
...@@ -311,3 +311,26 @@ TEST(Traits, remove_cvref) { ...@@ -311,3 +311,26 @@ TEST(Traits, remove_cvref) {
EXPECT_TRUE( EXPECT_TRUE(
(std::is_same<remove_cvref<int volatile const&&>::type, int>::value)); (std::is_same<remove_cvref<int volatile const&&>::type, int>::value));
} }
TEST(Traits, like) {
EXPECT_TRUE((std::is_same<like_t<int, char>, char>::value));
EXPECT_TRUE((std::is_same<like_t<int const, char>, char const>::value));
EXPECT_TRUE((std::is_same<like_t<int volatile, char>, char volatile>::value));
EXPECT_TRUE(
(std::is_same<like_t<int const volatile, char>, char const volatile>::
value));
EXPECT_TRUE((std::is_same<like_t<int&, char>, char&>::value));
EXPECT_TRUE((std::is_same<like_t<int const&, char>, char const&>::value));
EXPECT_TRUE(
(std::is_same<like_t<int volatile&, char>, char volatile&>::value));
EXPECT_TRUE(
(std::is_same<like_t<int const volatile&, char>, char const volatile&>::
value));
EXPECT_TRUE((std::is_same<like_t<int&&, char>, char&&>::value));
EXPECT_TRUE((std::is_same<like_t<int const&&, char>, char const&&>::value));
EXPECT_TRUE(
(std::is_same<like_t<int volatile&&, char>, char volatile&&>::value));
EXPECT_TRUE(
(std::is_same<like_t<int const volatile&&, char>, char const volatile&&>::
value));
}
...@@ -77,6 +77,14 @@ TEST_F(UtilityTest, as_const) { ...@@ -77,6 +77,14 @@ TEST_F(UtilityTest, as_const) {
EXPECT_TRUE(noexcept(folly::as_const(s))); EXPECT_TRUE(noexcept(folly::as_const(s)));
} }
TEST_F(UtilityTest, forward_like) {
int x = 0;
// just show that it may be invoked, and that it is purely a cast
// the real work is done by like_t, in terms of which forward_like is defined
EXPECT_EQ(&x, std::addressof(folly::forward_like<char&>(x)));
EXPECT_EQ(&x, std::addressof(folly::forward_like<char const>(x)));
}
TEST_F(UtilityTest, exchange) { TEST_F(UtilityTest, exchange) {
auto obj = std::map<std::string, int>{{"hello", 3}}; auto obj = std::map<std::string, int>{{"hello", 3}};
auto old = exchange(obj, {{"world", 4}}); auto old = exchange(obj, {{"world", 4}});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment