A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tuple.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Universita' degli Studi di Napoli Federico II
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Stefano Avallone <stavallo@unina.it>
18 */
19
20#ifndef TUPLE_H
21#define TUPLE_H
22
23#include "attribute-helper.h"
24#include "string.h"
25
26#include <algorithm>
27#include <sstream>
28#include <tuple>
29#include <type_traits>
30#include <utility>
31
32namespace ns3
33{
34
35/**
36 * \brief Stream insertion operator.
37 * See https://en.cppreference.com/w/cpp/utility/apply
38 *
39 * Prints tuple values separated by a comma. E.g., if the tuple contains
40 * v1, v2 and v3, then "v1, v2, v3" will be added to the stream.
41 *
42 * \tparam Args \deduced Tuple arguments
43 * \param os the output stream
44 * \param t the tuple
45 * \returns a reference to the stream
46 */
47template <class... Args>
48std::ostream&
49operator<<(std::ostream& os, const std::tuple<Args...>& t)
50{
51 std::apply(
52 [&os](auto&&... args) {
53 std::size_t n{0};
54 ((os << args << (++n != sizeof...(Args) ? ", " : "")), ...);
55 },
56 t);
57 return os;
58}
59
60/**
61 * \ingroup attributes
62 * \defgroup attribute_Tuple Tuple Attribute
63 * AttributeValue implementation for Tuple
64 */
65
66/**
67 * \ingroup attribute_Tuple
68 *
69 * AttributeValue implementation for Tuple.
70 *
71 * Hold objects of type std::tuple<Args...>.
72 * \tparam Args \explicit The list of AttributeValues to be held by this TupleValue
73 *
74 * \see AttributeValue
75 */
76template <class... Args>
78{
79 public:
80 /** Type of value stored in the TupleValue. */
81 typedef std::tuple<Args...> value_type;
82 /** Type returned by Get or passed in Set. */
83 typedef std::tuple<std::invoke_result_t<decltype(&Args::Get), Args>...> result_type;
84
85 TupleValue();
86
87 /**
88 * Construct this TupleValue from a std::tuple
89 *
90 * \param [in] value Value with which to construct.
91 */
92 TupleValue(const result_type& value);
93
94 Ptr<AttributeValue> Copy() const override;
95 bool DeserializeFromString(std::string value, Ptr<const AttributeChecker> checker) override;
96 std::string SerializeToString(Ptr<const AttributeChecker> checker) const override;
97
98 /**
99 * Get the stored values as a std::tuple.
100 *
101 * This differs from the actual value stored in the object which is
102 * a tuple of Ptr<AV> where AV is a class derived from AttributeValue.
103 * \return stored values as a std::tuple
104 */
105 result_type Get() const;
106 /**
107 * Set the stored values.
108 *
109 * \param value The stored value
110 */
111 void Set(const result_type& value);
112
113 /**
114 * Get the attribute values as a tuple.
115 * \return the attribute values as a tuple
116 */
117 value_type GetValue() const;
118
119 /**
120 * Set the given variable to the values stored by this TupleValue object.
121 *
122 * \tparam T \deduced the type of the given variable (normally, the argument type
123 * of a set method or the type of a data member)
124 * \param [out] value The stored value
125 * \return true if the given variable was set
126 */
127 template <typename T>
128 bool GetAccessor(T& value) const;
129
130 private:
131 /**
132 * Set the attribute values starting from the given values.
133 * Used by DeserializeFromString method.
134 *
135 * \tparam Is \deduced index sequence
136 * \param values the given attribute values
137 * \return true if the attribute values of this object were set
138 */
139 template <std::size_t... Is>
140 bool SetValueImpl(std::index_sequence<Is...>, const std::vector<Ptr<AttributeValue>>& values);
141
142 value_type m_value; //!< Tuple of attribute values
143};
144
145/**
146 * \ingroup attribute_Tuple
147 *
148 * Create a TupleValue object. Enable to write code like this snippet:
149 *
150 * \code
151 * typedef std::tuple<uint16_t, double> Tuple;
152 * typedef std::tuple<UintegerValue, DoubleValue> Pack;
153 *
154 * TupleValue<UintegerValue, DoubleValue> t = MakeTupleValue<Pack> (Tuple {10, 1.5});
155 * \endcode
156 *
157 * \tparam T1 \explicit A std::tuple of the AttributeValue types included in TupleValue
158 * \tparam T2 \deduced A std::tuple of the type of elements stored by TupleValue
159 * \param t the tuple of elements stored by TupleValue
160 * \return a TupleValue object
161 */
162template <class T1, class T2>
163auto MakeTupleValue(T2 t);
164
165/**
166 * \ingroup attribute_Tuple
167 *
168 * Checker for attribute values storing tuples.
169 */
171{
172 public:
173 /**
174 * Get the checkers for all tuple elements.
175 *
176 * \return the checkers for all tuple elements
177 */
178 virtual const std::vector<Ptr<const AttributeChecker>>& GetCheckers() const = 0;
179};
180
181/**
182 * \ingroup attribute_Tuple
183 *
184 * Create a TupleChecker from AttributeCheckers associated with TupleValue elements.
185 *
186 * \tparam Args \explicit Attribute value types
187 * \tparam Ts \deduced Attribute checker types
188 * \param checkers attribute checkers
189 * \return Pointer to TupleChecker instance.
190 */
191template <class... Args, class... Ts>
193
194/**
195 * \ingroup attribute_Tuple
196 *
197 * Create an AttributeAccessor for a class data member of type tuple,
198 * or a lone class get functor or set method.
199 *
200 * \tparam Args \explicit Attribute value types
201 * \tparam T1 \deduced The type of the class data member,
202 * or the type of the class get functor or set method.
203 * \param a1 The address of the data member,
204 * or the get or set method.
205 * \return the AttributeAccessor
206 */
207template <class... Args, class T1>
209
210/**
211 * \ingroup attribute_Tuple
212 *
213 * Create an AttributeAccessor using a pair of get functor
214 * and set methods from a class.
215 *
216 * \tparam Args \explicit Attribute value types
217 * \tparam T1 \deduced The type of the class data member,
218 * or the type of the class get functor or set method.
219 * \tparam T2 \deduced The type of the getter class functor method.
220 * \param a2 The address of the class method to set the attribute.
221 * \param a1 The address of the data member, or the get or set method.
222 * \return the AttributeAccessor
223 */
224template <class... Args, class T1, class T2>
226
227} // namespace ns3
228
229/*****************************************************************************
230 * Implementation below
231 *****************************************************************************/
232
233namespace ns3
234{
235
236template <class... Args>
238 : m_value(std::make_tuple(Args()...))
239{
240}
241
242template <class... Args>
244{
245 Set(value);
246}
247
248template <class... Args>
251{
252 return Create<TupleValue<Args...>>(Get());
253}
254
255template <class... Args>
256template <std::size_t... Is>
257bool
258TupleValue<Args...>::SetValueImpl(std::index_sequence<Is...>,
259 const std::vector<Ptr<AttributeValue>>& values)
260{
261 auto valueTuple = std::make_tuple(DynamicCast<Args>(values[Is])...);
262
263 bool ok = ((std::get<Is>(valueTuple) != nullptr) && ...);
264
265 if (ok)
266 {
267 m_value = std::make_tuple(Args(*std::get<Is>(valueTuple))...);
268 }
269 return ok;
270}
271
272template <class... Args>
273bool
275{
276 auto tupleChecker = DynamicCast<const TupleChecker>(checker);
277 if (!tupleChecker)
278 {
279 return false;
280 }
281
282 auto count = tupleChecker->GetCheckers().size();
283 if (count != sizeof...(Args))
284 {
285 return false;
286 }
287
288 if (value.empty() || value.front() != '{' || value.back() != '}')
289 {
290 return false;
291 }
292
293 value.erase(value.begin());
294 value.pop_back();
295 std::replace(value.data(), value.data() + value.size(), ',', ' ');
296
297 std::istringstream iss(value);
298 std::vector<Ptr<AttributeValue>> values;
299 std::size_t i = 0;
300
301 while (iss >> value)
302 {
303 if (i >= count)
304 {
305 return false;
306 }
307 values.push_back(tupleChecker->GetCheckers().at(i++)->CreateValidValue(StringValue(value)));
308 if (!values.back())
309 {
310 return false;
311 }
312 }
313
314 if (i != count)
315 {
316 return false;
317 }
318
319 return SetValueImpl(std::index_sequence_for<Args...>{}, values);
320}
321
322template <class... Args>
323std::string
325{
326 std::ostringstream oss;
327 oss << "{" << Get() << "}";
328 return oss.str();
329}
330
331template <class... Args>
332typename TupleValue<Args...>::result_type
334{
335 return std::apply([](Args... values) { return std::make_tuple(values.Get()...); }, m_value);
336}
337
338template <class... Args>
339void
341{
342 m_value = std::apply([](auto&&... args) { return std::make_tuple(Args(args)...); }, value);
343}
344
345template <class... Args>
346typename TupleValue<Args...>::value_type
348{
349 return m_value;
350}
351
352template <class... Args>
353template <typename T>
354bool
356{
357 value = T(Get());
358 return true;
359}
360
361// This internal class defines templated TupleChecker class that is instantiated
362// in MakeTupleChecker. The non-templated base ns3::TupleChecker is returned in that
363// function. This is the same pattern as ObjectPtrContainer.
364namespace internal
365{
366
367/**
368 * \ingroup attribute_Tuple
369 *
370 * Internal checker class templated to each AttributeChecker
371 * for each entry in the tuple.
372 */
373template <class... Args>
375{
376 public:
377 /**
378 * Constructor.
379 * \tparam Ts \deduced the type of the attribute checkers
380 * \param checkers the attribute checkers for individual elements of the tuple
381 */
382 template <class... Ts>
383 TupleChecker(Ts... checkers)
384 : m_checkers{checkers...}
385 {
386 }
387
388 const std::vector<Ptr<const AttributeChecker>>& GetCheckers() const override
389 {
390 return m_checkers;
391 }
392
393 bool Check(const AttributeValue& value) const override
394 {
395 const auto v = dynamic_cast<const TupleValue<Args...>*>(&value);
396 if (v == nullptr)
397 {
398 return false;
399 }
400 return std::apply(
401 [this](Args... values) {
402 std::size_t n{0};
403 return (m_checkers[n++]->Check(values) && ...);
404 },
405 v->GetValue());
406 }
407
408 std::string GetValueTypeName() const override
409 {
410 return "ns3::TupleValue";
411 }
412
413 bool HasUnderlyingTypeInformation() const override
414 {
415 return false;
416 }
417
418 std::string GetUnderlyingTypeInformation() const override
419 {
420 return "";
421 }
422
424 {
425 return ns3::Create<TupleValue<Args...>>();
426 }
427
428 bool Copy(const AttributeValue& source, AttributeValue& destination) const override
429 {
430 const auto src = dynamic_cast<const TupleValue<Args...>*>(&source);
431 auto dst = dynamic_cast<TupleValue<Args...>*>(&destination);
432 if (src == nullptr || dst == nullptr)
433 {
434 return false;
435 }
436 *dst = *src;
437 return true;
438 }
439
440 private:
441 std::vector<Ptr<const AttributeChecker>> m_checkers; //!< attribute checkers
442};
443
444/**
445 * \ingroup attribute_Tuple
446 *
447 * Helper class defining static methods for MakeTupleChecker and MakeTupleAccessor
448 * that are called when user specifies the list of AttributeValue types included
449 * in a TupleValue type.
450 */
451template <class... Args>
453{
454 /**
455 * \copydoc ns3::MakeTupleChecker
456 */
457 template <class... Ts>
459 {
460 return Create<internal::TupleChecker<Args...>>(checkers...);
461 }
462
463 /**
464 * \copydoc ns3::MakeTupleAccessor(T1)
465 */
466 template <class T1>
468 {
469 return MakeAccessorHelper<TupleValue<Args...>>(a1);
470 }
471
472 /**
473 * \copydoc ns3::MakeTupleAccessor(T1,T2)
474 */
475 template <class T1, class T2>
477 {
478 return MakeAccessorHelper<TupleValue<Args...>>(a1, a2);
479 }
480};
481
482/**
483 * \ingroup attribute_Tuple
484 *
485 * Helper class defining static methods for MakeTupleValue, MakeTupleChecker and
486 * MakeTupleAccessor that are called when user provides a std::tuple of the
487 * AttributeValue types included in a TupleValue type.
488 * This struct is a partial specialization of struct TupleHelper.
489 */
490template <class... Args>
491struct TupleHelper<std::tuple<Args...>>
492{
493 /**
494 * \copydoc ns3::MakeTupleValue
495 */
497 {
498 return TupleValue<Args...>(t);
499 }
500
501 /**
502 * \copydoc ns3::MakeTupleChecker
503 */
504 template <class... Ts>
506 {
507 return Create<internal::TupleChecker<Args...>>(checkers...);
508 }
509
510 /**
511 * \copydoc ns3::MakeTupleAccessor(T1)
512 */
513 template <class T1>
515 {
516 return MakeAccessorHelper<TupleValue<Args...>>(a1);
517 }
518
519 /**
520 * \copydoc ns3::MakeTupleAccessor(T1,T2)
521 */
522 template <class T1, class T2>
524 {
525 return MakeAccessorHelper<TupleValue<Args...>>(a1, a2);
526 }
527};
528
529} // namespace internal
530
531template <class T1, class T2>
532auto
534{
536}
537
538template <class... Args, class... Ts>
539Ptr<const AttributeChecker>
540MakeTupleChecker(Ts... checkers)
541{
542 return internal::TupleHelper<Args...>::template MakeTupleChecker<Ts...>(checkers...);
543}
544
545template <class... Args, class T1>
546Ptr<const AttributeAccessor>
548{
549 return internal::TupleHelper<Args...>::template MakeTupleAccessor<T1>(a1);
550}
551
552template <class... Args, class T1, class T2>
553Ptr<const AttributeAccessor>
554MakeTupleAccessor(T1 a1, T2 a2)
555{
556 return internal::TupleHelper<Args...>::template MakeTupleAccessor<T1, T2>(a1, a2);
557}
558
559} // namespace ns3
560
561#endif // TUPLE_H
Attribute helper (ATTRIBUTE_ )macros definition.
Represent the type of an attribute.
Definition: attribute.h:168
Hold a value for an Attribute.
Definition: attribute.h:70
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Hold variables of type string.
Definition: string.h:56
Checker for attribute values storing tuples.
Definition: tuple.h:171
virtual const std::vector< Ptr< const AttributeChecker > > & GetCheckers() const =0
Get the checkers for all tuple elements.
AttributeValue implementation for Tuple.
Definition: tuple.h:78
bool DeserializeFromString(std::string value, Ptr< const AttributeChecker > checker) override
Definition: tuple.h:274
std::string SerializeToString(Ptr< const AttributeChecker > checker) const override
Definition: tuple.h:324
void Set(const result_type &value)
Set the stored values.
Definition: tuple.h:340
bool GetAccessor(T &value) const
Set the given variable to the values stored by this TupleValue object.
Definition: tuple.h:355
std::tuple< Args... > value_type
Type of value stored in the TupleValue.
Definition: tuple.h:81
result_type Get() const
Get the stored values as a std::tuple.
Definition: tuple.h:333
Ptr< AttributeValue > Copy() const override
Definition: tuple.h:250
bool SetValueImpl(std::index_sequence< Is... >, const std::vector< Ptr< AttributeValue > > &values)
Set the attribute values starting from the given values.
Definition: tuple.h:258
std::tuple< std::invoke_result_t< decltype(&Args::Get), Args >... > result_type
Type returned by Get or passed in Set.
Definition: tuple.h:83
value_type GetValue() const
Get the attribute values as a tuple.
Definition: tuple.h:347
value_type m_value
Tuple of attribute values.
Definition: tuple.h:142
Internal checker class templated to each AttributeChecker for each entry in the tuple.
Definition: tuple.h:375
std::string GetUnderlyingTypeInformation() const override
Definition: tuple.h:418
bool HasUnderlyingTypeInformation() const override
Definition: tuple.h:413
std::string GetValueTypeName() const override
Definition: tuple.h:408
std::vector< Ptr< const AttributeChecker > > m_checkers
attribute checkers
Definition: tuple.h:441
TupleChecker(Ts... checkers)
Constructor.
Definition: tuple.h:383
const std::vector< Ptr< const AttributeChecker > > & GetCheckers() const override
Get the checkers for all tuple elements.
Definition: tuple.h:388
bool Check(const AttributeValue &value) const override
Definition: tuple.h:393
Ptr< AttributeValue > Create() const override
Definition: tuple.h:423
bool Copy(const AttributeValue &source, AttributeValue &destination) const override
Copy the source to the destination.
Definition: tuple.h:428
Ptr< const AttributeChecker > MakeTupleChecker(Ts... checkers)
Create a TupleChecker from AttributeCheckers associated with TupleValue elements.
Definition: tuple.h:540
Ptr< const AttributeAccessor > MakeTupleAccessor(T1 a1)
Create an AttributeAccessor for a class data member of type tuple, or a lone class get functor or set...
Definition: tuple.h:547
auto MakeTupleValue(T2 t)
Create a TupleValue object.
Definition: tuple.h:533
Ptr< const AttributeAccessor > MakeAccessorHelper(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition: ptr.h:447
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
STL namespace.
ns3::StringValue attribute value declarations.
static Ptr< const AttributeChecker > MakeTupleChecker(Ts... checkers)
Create a TupleChecker from AttributeCheckers associated with TupleValue elements.
Definition: tuple.h:505
static Ptr< const AttributeAccessor > MakeTupleAccessor(T1 a1)
Create an AttributeAccessor for a class data member of type tuple, or a lone class get functor or set...
Definition: tuple.h:514
static Ptr< const AttributeAccessor > MakeTupleAccessor(T1 a1, T2 a2)
Create an AttributeAccessor using a pair of get functor and set methods from a class.
Definition: tuple.h:523
static TupleValue< Args... > MakeTupleValue(const typename TupleValue< Args... >::result_type &t)
Create a TupleValue object.
Definition: tuple.h:496
Helper class defining static methods for MakeTupleChecker and MakeTupleAccessor that are called when ...
Definition: tuple.h:453
static Ptr< const AttributeChecker > MakeTupleChecker(Ts... checkers)
Create a TupleChecker from AttributeCheckers associated with TupleValue elements.
Definition: tuple.h:458
static Ptr< const AttributeAccessor > MakeTupleAccessor(T1 a1)
Create an AttributeAccessor for a class data member of type tuple, or a lone class get functor or set...
Definition: tuple.h:467
static Ptr< const AttributeAccessor > MakeTupleAccessor(T1 a1, T2 a2)
Create an AttributeAccessor using a pair of get functor and set methods from a class.
Definition: tuple.h:476