문제

I have this source file:

#include <ctime>

class A
{
  public:
    A(unsigned long i){};
    A(const tm*){};
};

int main(int argc, char** argv)
{
  A tit(1);
  A tat(0);
  return 0;
}

When I compile this using gcc 3.4.2 I get the following:

autoCast.cpp: In function int main(int, char**)':
autoCast.cpp:13: error: call of overloaded
A(int)' is ambiguous
autoCast.cpp:4: note: candidates are: A::A(const A&)
autoCast.cpp:7: note: A::A(const tm*)
autoCast.cpp:6: note: A::A(long unsigned int)

My question is: why does the creation of A tit(1) (line 12) succeed while A tat(0) (line 13) fails? I tried different argument types in those lines (e.g. 0ULL and 1ULL) but it always fails when the argument value is 0, while it succeeds when the argument value is 1. The only 0 value for which no error is raised is 0UL (because no conversion is needed I guess). Why in this case does an integer with value 0 get different treatment from an integer with value 1? Does it have to do with the tm struct defined in time.h?

도움이 되었습니까?

해결책

This is because 0 is a null pointer constant and can be converted to unsigned long or a pointer and therefore it is ambiguous which to choose. The draft C++ standard section 4.10 Pointer conversions says (emphasis mine):

A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type.

While 1 is not a null pointer constant. Although 0UL can be converted to a pointer as well it is a better match for the unsigned long constructor since no conversion is needed.

다른 팁

A literal 0 is often used to initialise a pointer to null (modern C++ should admittedly be using nullptr instead). However, it is comparatively uncommon to initialise pointers directly with any other integer literal (except in e.g. embedded systems which use memory mapping).

As such, the compiler is treating 0 as though it could be a pointer or an integer, meaning it could call either constructor. In contrast, it treats 1 simply as an integer.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top