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