在Mac OS X上使用size_t时,为什么uint32_t和uint64_t之间存在歧义?

时间:2012-07-22 20:38:54

标签: c++ macos gcc ambiguous

请考虑以下示例代码:

#include <iostream>
#include <inttypes.h>

using namespace std;

int f(uint32_t i)
{
  return 1;
}
int f(uint64_t i)
{
  return 2;
}

int main ()
{
  cout << sizeof(long unsigned) << '\n';
  cout << sizeof(size_t) << '\n';
  cout << sizeof(uint32_t) << '\n';
  cout << sizeof(uint64_t) << '\n';
  //long unsigned x = 3;
  size_t x = 3;
  cout << f(x) << '\n';
  return 0;
}

这在Mac OSX上失败:

$ g++ --version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
$ make test
g++     test.cc   -o test
test.cc: In function 'int main()':
test.cc:23: error: call of overloaded 'f(size_t&)' is ambiguous
test.cc:6: note: candidates are: int f(uint32_t)
test.cc:10: note:                 int f(uint64_t)
make: *** [test] Error 1

为什么呢?因为'size_t'应该是无符号的,32位或64位宽。那么模糊性在哪里?

尝试使用'unsigned long x'而不是'size_t x'会产生相同的结果 类似的歧义错误信息。

在Linux / Solaris系统上,使用不同的GCC版本,不同的体系结构等进行测试,没有报告歧义(并且在每个体系结构上使用了正确的重载)。

这是Mac OS X错误还是功能?

2 个答案:

答案 0 :(得分:9)

在Mac OS下,这些类型定义为:

typedef unsigned int         uint32_t;
typedef unsigned long long   uint64_t;

size_t定义为__SIZE_TYPE__的位置:

#if defined(__GNUC__) && defined(__SIZE_TYPE__)
typedef __SIZE_TYPE__       __darwin_size_t;    /* sizeof() */
#else
typedef unsigned long       __darwin_size_t;    /* sizeof() */
#endif

因此,如果您将代码更改为:

#include <iostream>
#include <inttypes.h>

using namespace std;

int f(uint32_t i)
{
  return 1;
}
int f(uint64_t i)
{
  return 2;
}

int f (unsigned long i)
{
  return 3;
}

int main ()
{
  cout << sizeof(unsigned long) << '\n';
  cout << sizeof(size_t) << '\n';
  cout << sizeof(uint32_t) << '\n';
  cout << sizeof(uint64_t) << '\n';
  //long unsigned x = 3;
  size_t x = 3;
  cout << f(x) << '\n';
  return 0;
}

然后运行它,你会得到:

$ g++ -o test test.cpp
$ ./test
8
8
4
8
3

答案 1 :(得分:4)

如果你真的想,你可以实现你想要的语义:

#define IS_UINT(bits, t) (sizeof(t)==(bits/8) && \
                          std::is_integral<t>::value && \
                          !std::is_signed<t>::value)

template<class T> auto f(T) -> typename std::enable_if<IS_UINT(32,T), int>::type
{
  return 1;
}

template<class T> auto f(T) -> typename std::enable_if<IS_UINT(64,T), int>::type
{
  return 2;
}

不是说这是个好主意;只是说你可以做到。

可能有一种很好的标准C ++方式来询问编译器&#34;这两种类型是否相同,你知道我的意思,不要对我愚蠢&#34;,但如果有的话,我不知道。

相关问题