对“uint32_t”的“long unsigned int”的模糊调用

时间:2014-02-23 16:56:01

标签: c++

我为所有[u]int{8|16|32|64}_t类型重载了一堆函数:

std::string f( uint8_t) { /*something*/ }
std::string f(  int8_t) { /*something*/ }
std::string f(uint16_t) { /*something*/ }
std::string f( int16_t) { /*something*/ }
std::string f(uint32_t) { /*something*/ }
std::string f( int32_t) { /*something*/ }
std::string f(uint64_t) { /*something*/ }
std::string f( int64_t) { /*something*/ }
//A few more overloads with a few more types (bool, float, const char*, etc.)

我现在使用long unsigned int类型的参数调用函数名称:

template <typename type_blah> class Something { public:
        //...
        std::string call_f(void) const {
            return f(*((type_blah*)(internal_variable)));
        }
        //...
};

这会产生错误:

  

错误:调用重载'f(long unsigned int&amp;)'是不明确的


我想这会发生,因为unsigned intuint32_t是不同的类型。但是,我不能为long unsigned int重载函数,因为这是一个冗余的定义。即:

std::string f(long unsigned int) { /*something*/ }

。 。 。生产:

  

错误:'std :: string f(uint32_t)'先前在这里定义


似乎类型机制相互作用:它无法确定要使用哪种转换,因为每次转换同样有效,但无法定义无转换过载,因为它已经存在。

我不能出于各种原因抛出论点。有没有办法解决这个问题?

平台是在Windows 7 x86-64上运行的g ++ MinGW x86。

3 个答案:

答案 0 :(得分:1)

您使用的是什么平台?

在Windows(Visual Studio 2010)上,unsigned long int与您提及的其他类型不同。

专门为该类型添加重载解决了错误。这个答案(和/或谷歌)可能会对这个问题有所了解:Type of unsigned long is different from uint32_t and uint64_t on Windows (VS2010)

我为unsigned long int定义了一个重载,如下所示:

std::string f( unsigned long int val )
{
  // Check that we chose the correct corresponding type
  // (This may vary by platform!)
  assert( sizeof( unsigned long int ) == sizeof( uint32_t ) );

  return f( static_cast<uint32_t>( val ) );
}

...在Visual Studio 2010中进行了测试,如下所示:

void main()
{
  std::cout << "sizeof( unsigned long int ): " << sizeof( unsigned long int ) << std::endl;
  std::cout << "sizeof( uint32_t ): "          << sizeof( uint32_t )          << std::endl;

  unsigned long int x = 1u;
  std::cout << f( x ) << std::endl;
}

......并得到了预期的结果:

sizeof( unsigned long int ): 4
sizeof( uint32_t ): 4
uint32_t

答案 1 :(得分:0)

以下是基于上面提供的代码的“测试”:

#include <string>
#include <cstdint>
#include <iostream>

std::string f( uint8_t) { return "ui8";}
std::string f(  int8_t) { return "i8";}
std::string f(uint16_t) { return "ui16";}
std::string f( int16_t) { return "i16";}
std::string f(uint32_t) { return "ui32";}
std::string f(unsigned long long int) { return "unsigned long long";}
std::string f(unsigned long int) { return "unsigned long";}
std::string f( int32_t) { return "i32";}
//std::string f(uint64_t) { return "ui64";}
std::string f( int64_t) { return "i64";}

int main()
{
    unsigned long x = 42;
    unsigned y = 17;
    uint32_t z = 9;
    uint64_t w = 135;
    std::cout << "x: "<< f(x) << " y: " << f(y) << " z: " << f(z) << " w: " << f(w) << std::endl;
}

示例输出:

$ clang++ ambig.cpp -std=c++0x -Wall -m64
$ ./a.out 
x: unsigned long y: ui32 z: ui32 w: unsigned long
$ clang++ ambig.cpp -std=c++0x -Wall -m32
$ ./a.out 
x: unsigned long y: ui32 z: ui32 w: unsigned long long

(我用clang ++复制了我的运行,但g ++的结果是相同的)

这可确保涵盖unsigned longunsigned long long类型。不幸的是,其中一个是uint64_t,因此必须将其删除。

如果确实将变量声明为unsigned long,则必须提供一个完全相同的函数 - 并且依赖它等同于uint32_t可能是不正确的 - 即使它们是相同的bitsize。

答案 2 :(得分:0)

既然您为每种类型(几乎?)定义了重载,那么您的函数应该是模板吗?

template < typename T >
std::string f( T )
{
  /*something*/
}

如果有一组代码适用于所有类型 - 甚至大多数类型 - 那么这将为您节省大量工作。

如果由于某种原因你还需要强制使用unsigned long int值的呼叫将其视为其他类型(如uint32_t),则可以在呼叫站点指定模板实例化:

return f<uint32_t>( *internal_variable );