core: Make all usual accessors available to AttributeContainerValue
This commit is contained in:
committed by
Stefano Avallone
parent
6a9a3b1f51
commit
ceb714e175
@@ -231,7 +231,6 @@ set(header_files
|
||||
model/assert.h
|
||||
model/attribute-accessor-helper.h
|
||||
model/attribute-construction-list.h
|
||||
model/attribute-container-accessor-helper.h
|
||||
model/attribute-container.h
|
||||
model/attribute-helper.h
|
||||
model/attribute.h
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2018 Caliola Engineering, LLC.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Jared Dulmage <jared.dulmage@caliola.com>
|
||||
*/
|
||||
|
||||
#ifndef ATTRIBUTE_CONTAINER_ACCESSOR_HELPER_H
|
||||
#define ATTRIBUTE_CONTAINER_ACCESSOR_HELPER_H
|
||||
|
||||
#include "attribute-container.h"
|
||||
|
||||
#include <ns3/attribute-helper.h>
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
#include <list>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* SFINAE compile time check if type T has const iterator.
|
||||
*/
|
||||
template <typename T>
|
||||
struct has_const_iterator
|
||||
{
|
||||
private:
|
||||
/// positive result
|
||||
typedef char yes;
|
||||
/// negative result
|
||||
typedef struct
|
||||
{
|
||||
char array[2]; //!< Check value, its size must be different than the "yes" size
|
||||
} no;
|
||||
|
||||
/**
|
||||
* Test function, compiled if type has a const_iterator
|
||||
* \return A value indicating that this specialization has been compiled.
|
||||
*/
|
||||
template <typename C> static yes test (typename C::const_iterator *);
|
||||
/**
|
||||
* Test function, compiled if type does not have a const_iterator
|
||||
* \return A value indicating that this specialization has been compiled.
|
||||
*/
|
||||
template <typename C> static no test (...);
|
||||
|
||||
public:
|
||||
/// Value of the test - true if type has a const_iterator
|
||||
static const bool value = sizeof (test<T> (0)) == sizeof (yes);
|
||||
/// Equivalent name of the type T
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
/**
|
||||
* SFINAE compile time check if type T has begin() and end() methods.
|
||||
*/
|
||||
template <typename T>
|
||||
struct has_begin_end
|
||||
{
|
||||
/**
|
||||
* Compiled if type T has a begin() method.
|
||||
* \return A value indicating that this specialization has been compiled.
|
||||
*/
|
||||
template <typename C> static char (&f (typename std::enable_if<
|
||||
std::is_same<decltype (static_cast<typename C::const_iterator (C::*) () const> (&C::begin)),
|
||||
typename C::const_iterator (C::*) () const>::value, void>::type *))[1];
|
||||
|
||||
/**
|
||||
* Compiled if type T does not have a begin() method.
|
||||
* \return A value indicating that this specialization has been compiled.
|
||||
*/
|
||||
template <typename C> static char (&f (...))[2];
|
||||
|
||||
/**
|
||||
* Compiled if type T has an end() method.
|
||||
* \return A value indicating that this specialization has been compiled.
|
||||
*/
|
||||
template <typename C> static char (&g (typename std::enable_if<
|
||||
std::is_same<decltype (static_cast<typename C::const_iterator (C::*) () const> (&C::end)),
|
||||
typename C::const_iterator (C::*) () const>::value, void>::type *))[1];
|
||||
|
||||
/**
|
||||
* Compiled if type T does not have an end() method.
|
||||
* \return A value indicating that this specialization has been compiled.
|
||||
*/
|
||||
template <typename C> static char (&g (...))[2];
|
||||
|
||||
/// True if type T has a begin() method.
|
||||
static bool const beg_value = sizeof (f<T> (0)) == 1;
|
||||
/// True if type T has an end() method.
|
||||
static bool const end_value = sizeof (g<T> (0)) == 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compile time check if type T is a container.
|
||||
*
|
||||
* Container here means has an iterator and supports begin() and end()
|
||||
* methods.
|
||||
*
|
||||
* Can be used when defining specializations when a type T is an STL
|
||||
* like container.
|
||||
*/
|
||||
template<typename T>
|
||||
struct is_container : std::integral_constant<bool, has_const_iterator<T>::value && has_begin_end<T>::beg_value && has_begin_end<T>::end_value>
|
||||
{ };
|
||||
|
||||
/**
|
||||
* \ingroup attributeimpl
|
||||
*
|
||||
* DoMakeAccessorHelperOne specialization for member containers
|
||||
*
|
||||
* The template parameter list contains an extra parameter that is
|
||||
* intended to disambiguate an attribute container from any other
|
||||
* templated attribute, e.g Ptr or Callback. Disambiguation is based
|
||||
* on begin/end and iterator.
|
||||
*
|
||||
* \tparam V \explicit The specific AttributeValue type to use to represent
|
||||
* the Attribute.
|
||||
* \tparam T \deduced The class holding the data member.
|
||||
* \tparam U \deduced The type of the container.
|
||||
* \tparam I \deduced The type of item (s) within the container.
|
||||
* \param [in] memberContainer The address of the data member.
|
||||
* \returns The AttributeAccessor.
|
||||
*/
|
||||
template <typename V, typename T, template <typename...> class U, typename ...I,
|
||||
typename = typename std::enable_if< ( is_container< U<I...> >::value ), void>::type >
|
||||
inline
|
||||
Ptr<const AttributeAccessor>
|
||||
DoMakeAccessorHelperOne (U<I...> T::*memberContainer)
|
||||
{
|
||||
/* AttributeAcessor implementation for a class member variable. */
|
||||
class MemberContainer : public AccessorHelper<T,V>
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Construct from a class data member address.
|
||||
* \param [in] memberContainer The class data member address.
|
||||
*/
|
||||
MemberContainer (U<I...> T::*memberContainer)
|
||||
: AccessorHelper<T,V> (),
|
||||
m_memberContainer (memberContainer)
|
||||
{}
|
||||
private:
|
||||
virtual bool DoSet (T *object, const V *v) const {
|
||||
// typename AccessorTrait<U<I>::value_type>::Result tmp;
|
||||
// bool ok = v->GetAccessor (tmp);
|
||||
// if (!ok)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
auto src = v->Get ();
|
||||
(object->*m_memberContainer).clear ();
|
||||
std::copy (src.begin (), src.end (), std::inserter ((object->*m_memberContainer), (object->*m_memberContainer).end ()));
|
||||
return true;
|
||||
}
|
||||
virtual bool DoGet (const T *object, V *v) const {
|
||||
v->Set (object->*m_memberContainer);
|
||||
return true;
|
||||
}
|
||||
virtual bool HasGetter (void) const {
|
||||
return true;
|
||||
}
|
||||
virtual bool HasSetter (void) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
U<I...> T::*m_memberContainer; // Address of the class data member.
|
||||
};
|
||||
return Ptr<const AttributeAccessor> (new MemberContainer (memberContainer), false);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // ATTRIBUTE_CONTAINER_ACCESSOR_HELPER_H
|
||||
@@ -39,11 +39,11 @@ class AttributeChecker;
|
||||
// A = attribute value type, C = container type to return
|
||||
/**
|
||||
* A container for one type of attribute.
|
||||
*
|
||||
*
|
||||
* The container uses \p A to parse items into elements.
|
||||
* Internally the container is always a list but an instance
|
||||
* can return the items in a container specified by \p C.
|
||||
*
|
||||
*
|
||||
* @tparam A AttributeValue type to be contained.
|
||||
* @tparam C Possibly templated container class returned by Get.
|
||||
*/
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
result_type Get (void) const;
|
||||
/**
|
||||
* Copy items from container c.
|
||||
*
|
||||
*
|
||||
* This method assumes \p c has stl-style begin and end methods.
|
||||
* The AttributeContainerValue value is cleared before copying from \p c.
|
||||
* @tparam T type of container.
|
||||
@@ -119,6 +119,17 @@ public:
|
||||
*/
|
||||
template <class T>
|
||||
void Set (const T &c);
|
||||
/**
|
||||
* Set the given variable to the values stored by this TupleValue object.
|
||||
*
|
||||
* \tparam T \deduced the type of the given variable (normally, the argument type
|
||||
* of a set method or the type of a data member)
|
||||
* \param value the given variable
|
||||
* \return true if the given variable was set
|
||||
*/
|
||||
template <typename T>
|
||||
bool GetAccessor (T &value) const;
|
||||
|
||||
|
||||
// NS3 interface
|
||||
/**
|
||||
@@ -166,8 +177,8 @@ public:
|
||||
|
||||
private:
|
||||
/**
|
||||
* Copy items from \ref begin to \ref end.
|
||||
*
|
||||
* Copy items from \ref begin to \ref end.
|
||||
*
|
||||
* The internal container is cleared before values are copied
|
||||
* using the push_back method.
|
||||
* @tparam ITER \deduced iterator type
|
||||
@@ -232,12 +243,31 @@ Ptr<AttributeChecker> MakeAttributeContainerChecker (void);
|
||||
* Make AttributeContainerAccessor using explicit types.
|
||||
* @tparam A AttributeValue type in container.
|
||||
* @tparam C Container type returned by Get.
|
||||
* \param[in] a1 AttributeContainer to be used.
|
||||
* \tparam T1 \deduced The type of the class data member,
|
||||
* or the type of the class get functor or set method.
|
||||
* \param [in] a1 The address of the data member,
|
||||
* or the get or set method.
|
||||
* \return AttributeContainerAccessor.
|
||||
*/
|
||||
template <typename A, template <typename...> class C=std::list, typename T1>
|
||||
Ptr<const AttributeAccessor> MakeAttributeContainerAccessor (T1 a1);
|
||||
|
||||
/**
|
||||
* Make AttributeContainerAccessor using explicit types.
|
||||
* @tparam A AttributeValue type in container.
|
||||
* @tparam C Container type returned by Get.
|
||||
* \tparam T1 \deduced The type of the class data member,
|
||||
* or the type of the class get functor or set method.
|
||||
*
|
||||
* \tparam T2 \deduced The type of the getter class functor method.
|
||||
* \param [in] a2 The address of the class method to set the attribute.
|
||||
* \param [in] a1 The address of the data member,
|
||||
* or the get or set method.
|
||||
* \return AttributeContainerAccessor.
|
||||
*/
|
||||
template <typename A, template <typename...> class C=std::list, typename T1, typename T2>
|
||||
Ptr<const AttributeAccessor> MakeAttributeContainerAccessor (T1 a1, T2 a2);
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -423,6 +453,17 @@ AttributeContainerValue<A, C>::Get (void) const
|
||||
return c;
|
||||
}
|
||||
|
||||
template <class A, template <class...> class C>
|
||||
template <typename T>
|
||||
bool
|
||||
AttributeContainerValue<A, C>::GetAccessor (T &value) const
|
||||
{
|
||||
result_type src = Get ();
|
||||
value.clear ();
|
||||
std::copy (src.begin (), src.end (), std::inserter (value, value.end ()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class A, template <class...> class C>
|
||||
template <class T>
|
||||
void
|
||||
@@ -506,6 +547,12 @@ Ptr<const AttributeAccessor> MakeAttributeContainerAccessor (T1 a1)
|
||||
return MakeAccessorHelper<AttributeContainerValue<A, C> > (a1);
|
||||
}
|
||||
|
||||
template <typename A, template <typename...> class C, typename T1, typename T2>
|
||||
Ptr<const AttributeAccessor> MakeAttributeContainerAccessor (T1 a1, T2 a2)
|
||||
{
|
||||
return MakeAccessorHelper<AttributeContainerValue<A, C> > (a1, a2);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // ATTRIBUTE_CONTAINER_H
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <ns3/test.h>
|
||||
#include <ns3/log.h>
|
||||
#include <ns3/attribute-container.h>
|
||||
#include <ns3/attribute-container-accessor-helper.h>
|
||||
#include <ns3/pair.h>
|
||||
#include <ns3/double.h>
|
||||
#include <ns3/integer.h>
|
||||
@@ -66,10 +65,23 @@ public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return The object TypeId.
|
||||
*/
|
||||
*/
|
||||
static
|
||||
TypeId GetTypeId ();
|
||||
|
||||
/**
|
||||
* Set the vector of ints to the given vector
|
||||
*
|
||||
* \param vec the given vector
|
||||
*/
|
||||
void SetIntVec (std::vector<int> vec);
|
||||
/**
|
||||
* Get the vector of ints
|
||||
*
|
||||
* \return the vector of ints
|
||||
*/
|
||||
std::vector<int> GetIntVec (void) const;
|
||||
|
||||
/**
|
||||
* \brief Stream insertion operator.
|
||||
*
|
||||
@@ -110,7 +122,9 @@ AttributeContainerObject::GetTypeId ()
|
||||
.AddAttribute ("IntegerVector", "Vector of integers",
|
||||
// the container value container differs from the underlying object
|
||||
AttributeContainerValue <IntegerValue> (),
|
||||
MakeAttributeContainerAccessor <IntegerValue> (&AttributeContainerObject::m_intvec),
|
||||
// the type of the underlying container cannot be deduced
|
||||
MakeAttributeContainerAccessor <IntegerValue, std::list> (&AttributeContainerObject::SetIntVec,
|
||||
&AttributeContainerObject::GetIntVec),
|
||||
MakeAttributeContainerChecker<IntegerValue> (MakeIntegerChecker<int> ()))
|
||||
.AddAttribute ("MapStringInt", "Map of strings to ints",
|
||||
// the container value container differs from the underlying object
|
||||
@@ -131,6 +145,18 @@ AttributeContainerObject::ReverseList ()
|
||||
m_intvec = tmp;
|
||||
}
|
||||
|
||||
void
|
||||
AttributeContainerObject::SetIntVec (std::vector<int> vec)
|
||||
{
|
||||
m_intvec = vec;
|
||||
}
|
||||
|
||||
std::vector<int>
|
||||
AttributeContainerObject::GetIntVec (void) const
|
||||
{
|
||||
return m_intvec;
|
||||
}
|
||||
|
||||
std::ostream &
|
||||
operator << (std::ostream &os, const AttributeContainerObject &obj)
|
||||
{
|
||||
@@ -147,7 +173,7 @@ operator << (std::ostream &os, const AttributeContainerObject &obj)
|
||||
|
||||
/**
|
||||
* \ingroup attribute-tests
|
||||
*
|
||||
*
|
||||
* This function handles mixed constness and compatible, yet
|
||||
* distinct numerical classes (like int and long)
|
||||
* \param x The left operand.
|
||||
@@ -163,7 +189,7 @@ operator ==(const std::pair<A, B> &x, const std::pair<C, D> &y)
|
||||
|
||||
/**
|
||||
* \ingroup attribute-tests
|
||||
*
|
||||
*
|
||||
* Test AttributeContainer instantiation, initialization, access
|
||||
*/
|
||||
class AttributeContainerTestCase : public TestCase
|
||||
@@ -269,7 +295,7 @@ AttributeContainerTestCase::DoRun ()
|
||||
|
||||
/**
|
||||
* \ingroup attribute-tests
|
||||
*
|
||||
*
|
||||
* Attribute serialization and deserialization TestCase.
|
||||
*/
|
||||
class AttributeContainerSerializationTestCase : public TestCase
|
||||
@@ -359,7 +385,7 @@ AttributeContainerSerializationTestCase::DoRun (void)
|
||||
|
||||
/**
|
||||
* \ingroup attribute-tests
|
||||
*
|
||||
*
|
||||
* Attribute set and get TestCase.
|
||||
*/
|
||||
class AttributeContainerSetGetTestCase : public TestCase
|
||||
@@ -462,7 +488,7 @@ AttributeContainerSetGetTestCase::DoRun (void)
|
||||
|
||||
/**
|
||||
* \ingroup attribute-tests
|
||||
*
|
||||
*
|
||||
* Attribute attribute container TestCase.
|
||||
*/
|
||||
class AttributeContainerTestSuite : public TestSuite
|
||||
|
||||
Reference in New Issue
Block a user