繁体   English   中英

“ uint32_t”的“ long unsigned int”模棱两可的调用

[英]Ambiguous Call of “long unsigned int” for “uint32_t”

对于所有[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&)'的调用不明确


我想会发生这种情况,因为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。

您正在使用什么平台?

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

专门为此类型添加重载即可解决该错误。 这个答案(和/或Google)可能会更清楚地说明此问题: unsigned long的类型与Windows(VS2010)上的uint32_t和uint64_t不同

我为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

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

#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可能是不正确的-即使它们的位大小相同。

由于您正在为(几乎?)每种类型定义重载,也许您的函数应该是模板?

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

如果有一套适用于所有(甚至大多数)类型的代码,那也可以节省很多工作。

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

return f<uint32_t>( *internal_variable );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM