函数的不明确重载,如“msg(long)”与候选“msg(int32_t)”和“msg(int64_t)”
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;
}
Greg一针见血:int32_t
和int64_t
是typedef,可能是也可能不是long
。如果两者都不是 typedef for long
,则重载解析可能会失败。long->int32_t
和long->int64_t
都有等级=升级(表12,13.3.3.1.2(
代码是否编译是实现定义的。 没有类型int32_t
也没有int64_t
;这些只是现有整型类型的 typedef。 如果类型恰好是已经重载的类型(int
、long
或long long
(,这几乎可以肯定是这种情况,那么你对同一个函数有多个定义。 如果它们位于同一翻译单元中,则为编译时错误,需要诊断。 如果它们在不同的翻译单元中,这是未定义的行为,但我想大多数实现也会产生错误。
在您的情况下,最好的解决方案可能是将msg
作为模板,并将键入的名称作为参数传递。
- 传递空初始值设定项列表时使用右值和左值引用候选项的重载解析
- 候选构造函数(隐式复制构造函数)不可行:第一个参数需要 l 值
- 如果函数采用指向类的指针,则函数将完全脱离候选列表
- 运算符表达式上下文中重载解析的内置运算符候选项的正确行为
- 解析.msg文件的标头流中的日期
- 候选函数不可行:没有从 std::vector<derived> 到 std::vector <base>的已知转换
- C++ - 候选函数不可行:没有从"结构"到"结构(&)"的已知转换
- 函数采用原始指针试图通过错误msg中概述的参考来接受指针
- 为什么GCC可以编译std::exception("some error msg")而没有错误?
- 注意:候选:MyClass:MyClass(const MyClass&) 错误
- MPI_Op_create:候选功能不可行.自定义结构指针不能解释为空指针
- 候选模板被忽略:推断的类型与调整后的类型不匹配
- C++。候选模板被忽略 - 无法将数组类型与自身匹配
- Hex_string to uint8_t msg[]
- C++ 候选构造函数不可行:没有已知的转换
- 错误:候选函数不可行:'this'参数具有类型 'const' 但方法未标记为 const
- 为什么候选"="运算符重载会被标记为 const?
- Windows MSG 结构与旧项目代码结构 MSG 冲突
- 输入法管理器函数 - 平假名到汉字候选列表 c++ covnersion 的正确调用顺序
- 函数的不明确重载,如“msg(long)”与候选“msg(int32_t)”和“msg(int64_t)”