候选“msg(int32_t)”和“msg(int64_t)”等函数的不明确的重载 [英] Ambiguous overload of functions like `msg(long)` with candidates `msg(int32_t)` and `msg(int64_t)`

查看:380
本文介绍了候选“msg(int32_t)”和“msg(int64_t)”等函数的不明确的重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:这非常类似于在编译时确定整数类型的位数,但是这是一个非常简化的版本,都包含在一个 .cpp

Note: This is very similar to Determine number of bits in integral type at compile time, however this is a much simplified version, all contained in a single .cpp

编辑:添加了一个解决方案 - 虽然给出了一个正确的解释

Edit: Added a solution - although a correct explanation was given (and accepted) I found a way to solve the problem generically.

问题出在

 msg(int32_t);
 msg(int64_t);

拨打

long long myLong = 6;
msg(myLong);    // Won't compile on gcc (4.6.3), call is ambiguous

。任何人都可以提供解释为什么这在gcc上失败(我假设它可能与事实gcc通常严格标准兼容)和如何正确实现相同的效果的示例?

This compiles on MSVC. Can anyone provide an explanation of why this fails on gcc (I'm assuming it's probably to do with the fact gcc is usually strictly standards compliant) and an example of how to correctly achieve the same effect?

#include <iostream>
#include <stdint.h>

#include <boost/integer.hpp>

using namespace std;

void msg(int v) { cout << "int: " << sizeof(int) << ' ' << v << '\n'; }
void msg(long v) { cout << "long: " << sizeof(long) << ' ' << v << '\n'; }
void msg(long long v) { cout << "long long: " << sizeof(long long) << ' ' << v << '\n'; }

void msg2(int32_t v) { cout << "int32_t: " << sizeof(int32_t) << ' ' << v << '\n'; }
void msg2(int64_t v) { cout << "int64_t: " << sizeof(int64_t) << ' ' << v << '\n'; }
void msg2(uint32_t v) { cout << "uint32_t: " << sizeof(uint32_t) << ' ' << v << '\n'; }
void msg2(uint64_t v) { cout << "uint64_t: " << sizeof(uint64_t) << ' ' << v << '\n'; }


int main()
{

    int myInt = -5;
    long myLong = -6L;
    long long myLongLong = -7LL;

    unsigned int myUInt = 5;
    unsigned int myULong = 6L;
    unsigned long long myULongLong = 7LL;

    msg(myInt);
    msg(myLong);
    msg(myLongLong);

    msg2(myInt);
    msg2(myLong);     // fails on gcc 4.6.3 (32 bit)
    msg2(myLongLong);

    msg2(myUInt);
    msg2(myULong);   // fails on gcc 4.6.3 (32 bit)
    msg2(myULongLong);

   return 0;
}

// Output from MSVC  (and gcc if you omit lines that would be commented out)
int: 4 5
long: 4 6
long long: 8 7
int32_t: 4 -5
int32_t: 4 -6   // omitted on gcc
int64_t: 8 -7
uint32_t: 4 5
uint32_t: 4 6   // omitted on gcc
uint64_t: 8 7



解决方案



解决方案提供了一个成功映射 int long long long 到相应的 int32_t int64_t 。这可以在运行时通过 if(sizeof(int)== sizeof(int32_t))类型语句来完成,但是编译时解决方案是更好的。编译时解决方案可通过使用 boost :: enable_if

Solution

The solution is provide a function that successfully maps int, long and long long to the appropriate int32_t or int64_t. This can be done trivially at run time via if (sizeof(int)==sizeof(int32_t)) type statements, but a compile-time solution is preferable. A compile-time solution is available via the use of boost::enable_if.

以下适用于MSVC10和gcc 4.6.3。
通过禁用非整型类型可以进一步增强解决方案,但这不在此问题的范围之内。

The following works on MSVC10 and gcc 4.6.3. The solution could be further enhanced by disabling for non-integral types, but that is outside the scope of this problem.

#include <iostream>
#include <stdint.h>

#include <boost/integer.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_signed.hpp>
#include <boost/type_traits/is_unsigned.hpp>

using namespace std;

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int32_t) && boost::is_signed<InputT>::value,
 int32_t>::type ConvertIntegral(InputT z) { return static_cast<int32_t>(z); }

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int64_t) && boost::is_signed<InputT>::value, 
int64_t>::type ConvertIntegral(InputT z) { return static_cast<int64_t>(z); }

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint32_t) && boost::is_unsigned<InputT>::value, 
uint32_t>::type ConvertIntegral(InputT z) { return static_cast<uint32_t>(z); }

template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint64_t) && boost::is_unsigned<InputT>::value, 
uint64_t>::type ConvertIntegral(InputT z) { return static_cast<uint64_t>(z); }

void msg(int v) { cout << "int: " << sizeof(int) << ' ' << v << '\n'; }
void msg(long v) { cout << "long: " << sizeof(long) << ' ' << v << '\n'; }
void msg(long long v) { cout << "long long: " << sizeof(long long) << ' ' << v << '\n'; }


void msg2(int32_t v) { cout << "int32_t: " << sizeof(int32_t) << ' ' << v << '\n'; }
void msg2(int64_t v) { cout << "int64_t: " << sizeof(int64_t) << ' ' << v << '\n'; }
void msg2(uint32_t v) { cout << "uint32_t: " << sizeof(uint32_t) << ' ' << v << '\n'; }
void msg2(uint64_t v) { cout << "uint64_t: " << sizeof(uint64_t) << ' ' << v << '\n'; }

int main()
{

    int myInt = -5;
    long myLong = -6L;
    long long myLongLong = -7LL;

    unsigned int myUInt = 5;
    unsigned int myULong = 6L;
    unsigned long long myULongLong = 7LL;

    msg(myInt);
    msg(myLong);
    msg(myLongLong);

    msg2(ConvertIntegral(myInt));
    msg2(ConvertIntegral(myLong));
    msg2(ConvertIntegral(myLongLong));

    msg2(ConvertIntegral(myUInt));
    msg2(ConvertIntegral(myULong));
    msg2(ConvertIntegral(myULongLong));

   return 0;
}


推荐答案

Greg head: int32_t int64_t 是typedef,可能或可能不是 long 。如果两个都不是 long 的typedef,重载解析可能失败。 long-> int32_t long-> int64_t 都有Rank = Promotion(表12,13.3.3.1。 2)

Greg hits the nail on the head: int32_t and int64_t are typedefs which may or may not be long. If neither is a typedef for long, overload resolution can fail. Both long->int32_t and long->int64_t have Rank=Promotion (Table 12, 13.3.3.1.2)

这篇关于候选“msg(int32_t)”和“msg(int64_t)”等函数的不明确的重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆