@@ -53,26 +53,42 @@ struct all_moves_noexcept
5353class ProtoValue {
5454 public:
5555 // / @brief Type discriminator constants for possible values stored in a ProtoValue.
56- enum Kind {
57- k_null = 0 ,
58- k_bool = 1 ,
59- k_double = 2 ,
60- k_string = 3 ,
61- k_list = 4 ,
62- k_struct = 5 ,
63- k_int = 6
64- };
56+ enum Kind { k_null = 0 , k_bool = 1 , k_double = 2 , k_string = 3 , k_list = 4 , k_struct = 5 };
6557
6658 // / @brief Construct a null object.
6759 ProtoValue () noexcept ;
6860
69- // / @brief Construct a nonempty object.
70- template <typename T>
71- ProtoValue (T t) noexcept (std::is_nothrow_move_constructible<T>{});
61+ // / @name Value constructors.
62+ // / @brief Constructors which initialize a ProtoValue holding its argument.
63+ // / @{
64+
65+ ProtoValue (std::nullptr_t ) noexcept ;
66+
67+ ProtoValue (bool b) noexcept ;
68+
69+ // / @brief Construct a double object upcast from constructor argument.
70+ ProtoValue (int i) noexcept ;
71+
72+ ProtoValue (double d) noexcept ;
73+
74+ ProtoValue (std::string s) noexcept ;
7275
7376 // / @brief Deduction helper constructor for string from string literal
7477 ProtoValue (const char * str);
7578
79+ // / @brief Construct from a ProtoList.
80+ template <typename Val = ProtoValue,
81+ typename = std::enable_if_t <std::is_same<Val, ProtoValue>{}>>
82+ ProtoValue (std::vector<Val>) noexcept (std::is_nothrow_move_constructible<std::vector<Val>>{});
83+
84+ // / @brief Construct from a ProtoStruct.
85+ template <typename Val = ProtoValue,
86+ typename = std::enable_if_t <std::is_same<Val, ProtoValue>{}>>
87+ ProtoValue (std::unordered_map<std::string, Val>) noexcept (
88+ std::is_nothrow_move_constructible<std::unordered_map<std::string, Val>>{});
89+
90+ // / @}
91+
7692 // / @brief Move construct this from other, leaving other in its unspecified-but-valid moved from
7793 // / state.
7894 ProtoValue (ProtoValue&& other) noexcept (proto_value_details::all_moves_noexcept{});
@@ -125,12 +141,12 @@ class ProtoValue {
125141 T const * get () const ;
126142
127143 // / @brief Return a reference to the underlying T, without checking.
128- // / @tparam T a bool, int, or double
144+ // / @tparam T a bool or double
129145 template <typename T>
130146 std::enable_if_t <std::is_scalar<T>{}, T&> get_unchecked ();
131147
132148 // / @brief Return the underlying T by value, without checking.
133- // / @tparam T a bool, int, or double.
149+ // / @tparam T a bool or double.
134150 template <typename T>
135151 std::enable_if_t <std::is_scalar<T>{}, T> get_unchecked () const ;
136152
@@ -204,7 +220,6 @@ class ProtoValue {
204220 using BufType = std::aligned_union_t <0 ,
205221 std::nullptr_t ,
206222 bool ,
207- int ,
208223 double ,
209224 std::string,
210225 std::vector<void *>,
@@ -257,6 +272,11 @@ class ProtoValue {
257272
258273 ProtoValue (const google::protobuf::Value* value);
259274
275+ // Helper template for the explicit versions above.
276+ // Includes nullptr_t as a tag type so we can let the other constructors delegate.
277+ template <typename T>
278+ ProtoValue (T t, std::nullptr_t ) noexcept (std::is_nothrow_move_constructible<T>{});
279+
260280 vtable vtable_;
261281 storage self_;
262282};
@@ -275,24 +295,16 @@ using ProtoList = std::vector<ProtoValue>;
275295using ProtoStruct = std::unordered_map<std::string, ProtoValue>;
276296
277297// -- Template specialization declarations of by-value constructors -- //
278- extern template ProtoValue::ProtoValue(std::nullptr_t ) noexcept ;
279- extern template ProtoValue::ProtoValue(bool ) noexcept ;
280- extern template ProtoValue::ProtoValue(int ) noexcept ;
281- extern template ProtoValue::ProtoValue(double ) noexcept ;
282- extern template ProtoValue::ProtoValue(std::string) noexcept (
283- std::is_nothrow_move_constructible<std::string>{});
284298extern template ProtoValue::ProtoValue(ProtoList) noexcept (
285299 std::is_nothrow_move_constructible<ProtoList>{});
286300extern template ProtoValue::ProtoValue(ProtoStruct m) noexcept (
287301 std::is_nothrow_move_constructible<ProtoStruct>{});
288302
289303// -- Template specialization declarations of get_unchecked: POD types -- //
290304extern template bool & ProtoValue::get_unchecked<bool >();
291- extern template int & ProtoValue::get_unchecked<int >();
292305extern template double & ProtoValue::get_unchecked<double >();
293306
294307extern template bool ProtoValue::get_unchecked<bool >() const ;
295- extern template int ProtoValue::get_unchecked<int >() const ;
296308extern template double ProtoValue::get_unchecked<double >() const ;
297309
298310// -- Template specialization declarations of get_unchecked: string and recursive types -- //
@@ -310,7 +322,6 @@ extern template ProtoStruct&& ProtoValue::get_unchecked<ProtoStruct>() &&;
310322
311323void to_proto (std::nullptr_t , google::protobuf::Value* v);
312324void to_proto (bool b, google::protobuf::Value* v);
313- void to_proto (int i, google::protobuf::Value* v);
314325void to_proto (double d, google::protobuf::Value* v);
315326void to_proto (std::string s, google::protobuf::Value* v);
316327void to_proto (const ProtoList& vec, google::protobuf::Value* v);
@@ -371,11 +382,6 @@ struct kind<bool> {
371382 using type = KindConstant<ProtoValue::Kind::k_bool>;
372383};
373384
374- template <>
375- struct kind <int > {
376- using type = KindConstant<ProtoValue::Kind::k_int>;
377- };
378-
379385template <>
380386struct kind <double > {
381387 using type = KindConstant<ProtoValue::Kind::k_double>;
0 commit comments