[Ns-developers] Ipv4Address and Ipv4Mask, getting rid of "implicit" constructors
Gustavo Carneiro
gjcarneiro at gmail.com
Wed May 14 04:54:18 PDT 2008
2008/5/14 <craigdo at ee.washington.edu>:
>
> > > I would like to make all these constructors "explicit",
> > thus you have to
> > > type Ipv4Address ("1.2.3.4") instead of "1.2.3.4".
> > >
> > > Comments?
> >
> > +1: avoids many implicit conversion traps.
>
> It's a lot of "extra" typing for manual address assignment, but now that
> we
> have automagic IP address generation in place I don't see it as being a
> huge
> nuisance.
Extra typing but comes with extra readability.
> Of course, the tutorial uses this as an example of how type implicit type
> conversion works, so it's my turn to have the same reaction as Gustavo
> about
> API changes. Every time we make a change like this it obsoletes large
> sections of documentation. I suppose we could change the implicit type
> section to talk about node helpers, but it's more work.
Sorry. I do hate API changes. OTOH this would be really a minor change
compared to others we have seen... :-)
So, this is one argument against the change.
> What kind of traps are you trying to avoid? Can you give me an
> illustration
> of what would be a plausible scenario that would be avoided?
My main gripe is that I do not expect automatic conversion and associated
compilation error messages always baffle me for a couple of minutes. Maybe
it's because I'm no C++ guru that I don't expect this, I don't know.
Last time I saw this I was passing uint32_t to a function expecting
Ipv4Address[1] and it gave me such a strange error message.
Now I can also show an example of disabling builtin C++ type checking:
void CreateNode (const char *name, Ipv4Address mainAddress);
You could accidentally call it like this:
CreateNode ("10.0.0.1", "MobileTerminal");
It would compile perfectly and only fail in runtime (mysteriously if
Ipv4Address does poor parsing job).
Or:
void AddInterface (Ipv4Address mainAddress, Ipv4Address mask);
AddInterface ("255.255.0.0", "10.0.0.1");
The last example I can think of is problems with overloaded functions or
methods. See for example:
------------------------------------------------------------------------------
#include <iostream>
class Ipv4Address
{
public:
Ipv4Address (const char *addrString) {}
};
class Ipv4Mask
{
public:
Ipv4Mask (const char *maskString) {}
};
void DoSomethingWithAddress (Ipv4Address addr)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void DoSomethingWithMask (Ipv4Mask addr)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void DoSomething (Ipv4Address addr)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main ()
{
DoSomethingWithAddress ("1.2.3.4");
DoSomethingWithMask ("1.2.3.4");
DoSomething ("1.2.3.4");
return 0;
}
------------------------------------------------------------------------------
Suppose that main is the user code, and everything else is the NS-3
library. The user code compiles fine.
Now suppose a new NS-3 release adds an overloaded method:
void DoSomething (Ipv4Mask addr)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Suddenly, and confusingly, the program stops compiling:
test1.cc: In function 'int main()':
test1.cc:40: error: call of overloaded 'DoSomething(const char [8])' is
ambiguous
test1.cc:26: note: candidates are: void DoSomething(Ipv4Address)
test1.cc:31: note: void DoSomething(Ipv4Mask)
[1] I had already disabled the implicit constructor from uint32_t because I
was bitten by lack of type checking before due to this implicit conversion.
--
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert
More information about the Ns-developers
mailing list