Неоднозначная перегрузка функций типа `msg (long)` с кандидатами `msg (int32_t)` и `msg (int64_t)`
Note: Это очень похоже наОпределить количество бит в целочисленном типе во время компиляцииОднако, это очень упрощенная версия, все содержится в одном.cpp
Edit: Добавлено решение - хотя и правильноеexplanation был дан (и принят), я нашел способ решить проблему в общем.
ProblemПроблема с такими функциями, как
<code> msg(int32_t); msg(int64_t); </code>
звонок как
<code>long long myLong = 6; msg(myLong); // Won't compile on gcc (4.6.3), call is ambiguous </code>
Это компилируется на MSVC. Может ли кто-нибудь дать объяснение, почему это не работает на gcc (я предполагаю, что это, вероятно, связано с тем, что gcc обычно строго соответствует стандартам), и пример того, как правильно достичь того же эффекта?
<code>#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 </code>Solution
Решение состоит в том, чтобы обеспечить функцию, которая успешно отображаетint
, long
а такжеlong long
к соответствующемуint32_t
или жеint64_t
, Это можно сделать тривиально во время выполнения с помощьюif (sizeof(int)==sizeof(int32_t))
операторы типа, но решение во время компиляции предпочтительнее. Решение времени компиляции доступно через использованиеboost::enable_if
.
Следующие работы на MSVC10 и gcc 4.6.3. Решение может быть дополнительно улучшено путем отключения для нецелых типов, но это выходит за рамки этой проблемы.
<code>#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; } </code>