Commit 8f8a5e47 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Move in_place and friends to Utility.h

Summary:
[Folly] Move `in_place` and friends to `Utility.h`.

Document that they are backports from C++17.

Reviewed By: Orvid

Differential Revision: D5362364

fbshipit-source-id: 495cb7f339fc558f20d89100c141fc7a243239d5
parent 6b73d5f5
......@@ -36,6 +36,7 @@
#include <folly/FBString.h>
#include <folly/Portability.h>
#include <folly/Traits.h>
#include <folly/Utility.h>
#ifdef __GNUC__
#pragma GCC diagnostic push
......
......@@ -32,8 +32,9 @@
#include <folly/Likely.h>
#include <folly/Portability.h>
#include <folly/Preprocessor.h>
#include <folly/Traits.h> // for in_place_t
#include <folly/Traits.h>
#include <folly/Unit.h>
#include <folly/Utility.h>
#define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__)
......
......@@ -606,92 +606,6 @@ bool greater_than(LHS const lhs) {
RHS, rhs, typename std::remove_reference<LHS>::type
>(lhs);
}
namespace traits_detail {
struct InPlaceTag {};
template <class>
struct InPlaceTypeTag {};
template <std::size_t>
struct InPlaceIndexTag {};
}
/**
* Like std::piecewise_construct, a tag type & instance used for in-place
* construction of non-movable contained types, e.g. by Synchronized.
* Follows the naming and design of std::in_place suggested in
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0032r2.pdf
*/
using in_place_t = traits_detail::InPlaceTag (&)(traits_detail::InPlaceTag);
template <class T>
using in_place_type_t =
traits_detail::InPlaceTypeTag<T> (&)(traits_detail::InPlaceTypeTag<T>);
template <std::size_t I>
using in_place_index_t =
traits_detail::InPlaceIndexTag<I> (&)(traits_detail::InPlaceIndexTag<I>);
inline traits_detail::InPlaceTag in_place(traits_detail::InPlaceTag = {}) {
return {};
}
template <class T>
inline traits_detail::InPlaceTypeTag<T> in_place_type(
traits_detail::InPlaceTypeTag<T> = {}) {
return {};
}
template <std::size_t I>
inline traits_detail::InPlaceIndexTag<I> in_place_index(
traits_detail::InPlaceIndexTag<I> = {}) {
return {};
}
/**
* Initializer lists are a powerful compile time syntax introduced in C++11
* but due to their often conflicting syntax they are not used by APIs for
* construction.
*
* Further standard conforming compilers *strongly* favor an
* std::initalizer_list overload for construction if one exists. The
* following is a simple tag used to disambiguate construction with
* initializer lists and regular uniform initialization.
*
* For example consider the following case
*
* class Something {
* public:
* explicit Something(int);
* Something(std::intiializer_list<int>);
*
* operator int();
* };
*
* ...
* Something something{1}; // SURPRISE!!
*
* The last call to instantiate the Something object will go to the
* initializer_list overload. Which may be surprising to users.
*
* If however this tag was used to disambiguate such construction it would be
* easy for users to see which construction overload their code was referring
* to. For example
*
* class Something {
* public:
* explicit Something(int);
* Something(folly::initlist_construct_t, std::initializer_list<int>);
*
* operator int();
* };
*
* ...
* Something something_one{1}; // not the initializer_list overload
* Something something_two{folly::initlist_construct, {1}}; // correct
*/
struct initlist_construct_t {};
constexpr initlist_construct_t initlist_construct{};
} // namespace folly
// Assume nothing when compiling with MSVC.
......
......@@ -132,6 +132,85 @@ using make_index_sequence = detail::make_index_sequence<N>;
#endif
/**
* Backports from C++17 of:
* std::in_place_t
* std::in_place_type_t
* std::in_place_index_t
* std::in_place
* std::in_place_type
* std::in_place_index
*/
struct in_place_tag {};
template <class>
struct in_place_type_tag {};
template <std::size_t>
struct in_place_index_tag {};
using in_place_t = in_place_tag (&)(in_place_tag);
template <class T>
using in_place_type_t = in_place_type_tag<T> (&)(in_place_type_tag<T>);
template <std::size_t I>
using in_place_index_t = in_place_index_tag<I> (&)(in_place_index_tag<I>);
inline in_place_tag in_place(in_place_tag = {}) {
return {};
}
template <class T>
inline in_place_type_tag<T> in_place_type(in_place_type_tag<T> = {}) {
return {};
}
template <std::size_t I>
inline in_place_index_tag<I> in_place_index(in_place_index_tag<I> = {}) {
return {};
}
/**
* Initializer lists are a powerful compile time syntax introduced in C++11
* but due to their often conflicting syntax they are not used by APIs for
* construction.
*
* Further standard conforming compilers *strongly* favor an
* std::initalizer_list overload for construction if one exists. The
* following is a simple tag used to disambiguate construction with
* initializer lists and regular uniform initialization.
*
* For example consider the following case
*
* class Something {
* public:
* explicit Something(int);
* Something(std::intiializer_list<int>);
*
* operator int();
* };
*
* ...
* Something something{1}; // SURPRISE!!
*
* The last call to instantiate the Something object will go to the
* initializer_list overload. Which may be surprising to users.
*
* If however this tag was used to disambiguate such construction it would be
* easy for users to see which construction overload their code was referring
* to. For example
*
* class Something {
* public:
* explicit Something(int);
* Something(folly::initlist_construct_t, std::initializer_list<int>);
*
* operator int();
* };
*
* ...
* Something something_one{1}; // not the initializer_list overload
* Something something_two{folly::initlist_construct, {1}}; // correct
*/
struct initlist_construct_t {};
constexpr initlist_construct_t initlist_construct{};
/**
* A simple function object that passes its argument through unchanged.
*
......
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