Resolve unsigned long / pointer ambiguity

603 Views Asked by At

Our legacy code is using RogueWave library. I am trying to construct a RWTime object from a 0 literal. However, anything I do doesn't seem to have an effect and the compiler still have two constructors to select from:

error: call of overloaded 'RWTime(int)' is ambiguous
   _time(static_cast<unsigned long>(0))
                                      ^
note: candidates are:
RWTime::RWTime(const tm*, const RWZone&)
     RWTime(const struct tm* ptm, const RWZone& zone = RWZone::local());
     ^
RWTime::RWTime(long unsigned int)
     RWTime(unsigned long s)
     ^
constexpr RWTime::RWTime(const RWTime&)
 class RW_DEPRECATE_TYPE("Use RWDateTime instead") RW_TOOLS_SYMBOLIC RWTime
                                                                     ^
constexpr RWTime::RWTime(RWTime&&)

I would like to use the unsigned long constructor, but I don't seem to be able to actually pass unsigned long. I tried:

_time(static_cast<unsigned long>(0))
_time((unsigned long)0)
_time(0UL)
_time(0)

but no effect. Maybe the problem is that a pointer has uintptr_t type, which is synonymous to size_t type which is synonymous to unsigned long. And then there are actually two constructors taking unsigned long.

EDIT: I checked the RWTime class documentation and they mention the problem: "The compiler can parse 0 as either an integer or a pointer. Since there is also a constructor that takes a pointer (to struct tm), if you want to construct a time from the unsigned long value 0, you must be explicit:

RWTime earlyTime((unsigned long)0);

However, for some reason it doesn't work for me (using c++11).

3

There are 3 best solutions below

0
On BEST ANSWER

Turned out I was having a look at wrong piece of code after all.

_time(0UL)

works like a charm.

2
On

If you can use c11 you can't override your problem using nullptr and nullptr_t: The compiler can choose between a pointer and a int function when value is 0 (or NULL that is 0 also).

You have to define a new function that accept nullptr_t for avoid ambiguous:

   RWTime::RWTime( std::nullptr_t np)

And, of course, use std::nullptr for null pointers

As you point that is not possible to change library code I propose a second solution: Define an intermediate variable to give a clue to compiler which function must choose

    unsigned long tmp = 0;
    _time(tmp);

Another way can be give the second parameter:

     _time(0, RWZone::local());
2
On

If it is acceptable to you, you could take out the default value for RWZone in the constructor:

RWTime(const struct tm* ptm, const RWZone& zone = RWZone::local());

So that it reads:

RWTime(const struct tm* ptm, const RWZone& zone);

Then the 0 cannot be taken for this because the RWZone argument would be missing.

Of course you could add a static method that allowed you to create a RWTime object that only takes a const struct tm* like so:

static RWTime create(const struct tm* ptm) { return RWTime(ptr, RWZone::local()); }