Bug 2780 - Pass an arbitrary number of arguments to ObjectFactory::Set
Pass an arbitrary number of arguments to ObjectFactory::Set
Status: RESOLVED MOVED
Product: ns-3
Classification: Unclassified
Component: core
pre-release
All All
: P3 enhancement
Assigned To: Peter Barnes
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2017-09-04 14:03 UTC by Stefano Avallone
Modified: 2020-05-06 10:54 UTC (History)
2 users (show)

See Also:


Attachments
C++11 version of the patch (43.43 KB, patch)
2017-09-04 14:03 UTC, Stefano Avallone
Details | Diff
C++14 version of the patch (43.14 KB, patch)
2017-09-04 14:04 UTC, Stefano Avallone
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Stefano Avallone 2017-09-04 14:03:54 UTC
Created attachment 2911 [details]
C++11 version of the patch

Variadic templates allow to pass an arbitrary number of arguments to ObjectFactory::Set, so that helper functions (and CreateObjectWithAttributes<T>()) can be greatly simplified and allow arbitrary number of arguments. For instance:

template<typename T>
Ptr<T>
CreateObjectWithAttributes (std::string n1, const AttributeValue & v1,
                            std::string n2, const AttributeValue & v2,
                            std::string n3, const AttributeValue & v3,
                            std::string n4, const AttributeValue & v4,
                            std::string n5, const AttributeValue & v5,
                            std::string n6, const AttributeValue & v6,
                            std::string n7, const AttributeValue & v7,
                            std::string n8, const AttributeValue & v8,
                            std::string n9, const AttributeValue & v9)
{
  ObjectFactory factory;
  factory.SetTypeId (T::GetTypeId ());
  factory.Set (n1, v1);
  factory.Set (n2, v2);
  factory.Set (n3, v3);
  factory.Set (n4, v4);
  factory.Set (n5, v5);
  factory.Set (n6, v6);
  factory.Set (n7, v7);
  factory.Set (n8, v8);
  factory.Set (n9, v9);
  return factory.Create<T> ();
}

becomes


template<typename T, typename... Args>
Ptr<T>
CreateObjectWithAttributes (Args... args)
{
  ObjectFactory factory;
  factory.SetTypeId (T::GetTypeId ());
  factory.Set (args...);
  return factory.Create<T> ();
}

I did not implement the "recursive" approach (Set consumes two arguments and calls itself), but an approach where all the name-value pairs are used to initialize a map and then set by calling the DoSet member function (which is exactly the current Set member function).

I used this approach to simplify the traffic-control helper and verified that the python bindings can be scanned (with castxml, 64-bit only) and ns-3 builds on Linux (g++-4.9 and g++-7.1) and Mac OSX (clang 8.1).

I also prepared a C++14 version of the patch, where I could avoid defining index_sequence and make_index_sequence and reuse std::index_sequence and std::make_index_sequence.

I switched ns-3 to using C++14 and:

- ns-3 builds on Mac OSX (clang 8.1) and Linux (g++ 7.1)
- ns-3 does not build on Linux with g++ 4.9, not because of this patch but because of the pattern below used in the emulation devices:

char control[CMSG_SPACE (msg_size)];
...
msg.msg_controllen = sizeof (control);

"error: taking sizeof array of runtime bound"

I think it is anyway safe to replace 

msg.msg_controllen = sizeof (control);

with

msg.msg_controllen = CMSG_SPACE (msg_size) * sizeof (char);

After that, everything builds and runs just fine.
Comment 1 Stefano Avallone 2017-09-04 14:04:26 UTC
Created attachment 2912 [details]
C++14 version of the patch
Comment 2 Robert Ammon 2017-09-04 20:58:40 UTC
Comment on attachment 2912 [details]
C++14 version of the patch

In object-factory.h for the SetImpl declaration you use the following.  Is the \tparam in the DOXYGEN declaration intentional?

\tparam T \explicit The requested Object type.
Comment 3 Stefano Avallone 2017-09-05 03:25:11 UTC
(In reply to Robert Ammon from comment #2)
> Comment on attachment 2912 [details]
> C++14 version of the patch
> 
> In object-factory.h for the SetImpl declaration you use the following.  Is
> the \tparam in the DOXYGEN declaration intentional?
> 
> \tparam T \explicit The requested Object type.

It was already there, I didn't add it intentionally.

Anyway, I didn't pay much attention to doxygen and documentation for now. Should this patch be accepted, I will of course fix doxygen and documentation.
Comment 4 Stefano Avallone 2020-05-06 10:54:34 UTC
Moved to GitLab:

https://gitlab.com/nsnam/ns-3-dev/-/merge_requests/276