Added initlist_construct_t tag for explicit initializer list
authorAaryaman Sagar <aary@instagram.com>
Sat, 30 Jul 2016 03:30:00 +0000 (20:30 -0700)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Sat, 30 Jul 2016 03:38:25 +0000 (20:38 -0700)
Summary:
Initializer list construction can often have conflictingly similar
syntax as uniform initialization.  As a result APIs and classes often either
avoid using `std::initializer_list`s or deprecate construction with
`std::initializer_list`s.  This change provides a tag similar to
`std::piecewise_construct_t` to help out.

Reviewed By: simpkins

Differential Revision: D3617276

fbshipit-source-id: 3c74802f946a22e1a4ee52eca0f89df4a028eb22

folly/Traits.h

index 6ea1c4b109aede6fe1fd70fe124c4c7b0d0951ca..c50948ccff8a9438dfe586e8173050469ad4da7a 100644 (file)
@@ -405,6 +405,51 @@ bool greater_than(LHS const lhs) {
 struct construct_in_place_t {};
 constexpr construct_in_place_t construct_in_place{};
 
 struct construct_in_place_t {};
 constexpr construct_in_place_t construct_in_place{};
 
+/**
+ * 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
 
 // gcc-5.0 changed string's implementation in libgcc to be non-relocatable
 } // namespace folly
 
 // gcc-5.0 changed string's implementation in libgcc to be non-relocatable