[英]Ambiguous overload of functions like `msg(long)` with candidates `msg(int32_t)` and `msg(int64_t)`
注意:这与在编译时确定整数类型的位数非常相似,但是这是一个非常简化的版本,全部包含在单个.cpp
编辑 :添加了一个解决方案-尽管给出了正确的解释 (并被接受),但我找到了一种一般解决问题的方法。
问题出在像
msg(int32_t);
msg(int64_t);
像这样的电话
long long myLong = 6;
msg(myLong); // Won't compile on gcc (4.6.3), call is ambiguous
这可以在MSVC上编译。 谁能解释为什么这在gcc上失败(我认为这可能与gcc通常严格符合标准这一事实有关)以及如何正确实现相同效果的示例?
#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
获得编译时解决方案。
以下内容适用于MSVC10和gcc 4.6.3。 通过禁用非整数类型可以进一步增强该解决方案,但这不在此问题的范围内。
#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;
}
代码是否将编译取决于实现。 没有类型int32_t
和int64_t
; 这些只是现有整数类型的typedef。 如果类型恰好是已经重载的类型( int
, long
或long long
)(几乎可以肯定是这种情况),则您对同一函数有多个定义。 如果它们在同一个翻译单元中,则是编译时错误,需要进行诊断。 如果它们位于不同的翻译单元中,则这是未定义的行为,但是我想大多数实现也会产生错误。
在您的情况下,最好的解决方案可能是将msg
用作模板,然后将类型名称作为参数传递。
Greg碰到了头: int32_t
和int64_t
是typedef,它们可能很long
也可能不会很long
。 如果long
都不是typedef,则重载解析可能会失败。 long->int32_t
和long->int64_t
均具有Rank = Promotion(表12、13.3.3.1.2)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.