Trong VC++ 2010 có ba quá tải của std::to_string
mà phải mất long long
, unsigned long long
, và long double
, tương ứng - rõ ràng int
là không ai trong số này, và không có ai chuyển đổi là tốt hơn so với khác (demo), do đó việc chuyển đổi không thể được thực hiện ngầm/unambiguously.
Xét về hỗ trợ thực C++ 11, đây là một thất bại trên một phần của VC++ thực hiện tiêu chuẩn thư viện năm 2010 - tiêu chuẩn C++ 11 bản thân thực sự đòi hỏi chín quá tải của std::to_string
([string.conversions]/7):
string to_string(int val);
string to_string(unsigned val);
string to_string(long val);
string to_string(unsigned long val);
string to_string(long long val);
string to_string(unsigned long long val);
string to_string(float val);
string to_string(double val);
string to_string(long double val);
đã tất cả các quá tải có mặt, bạn rõ ràng là sẽ không có vấn đề này; tuy nhiên, VC++ 2010 không dựa trên tiêu chuẩn C++ 11 thực tế (mà chưa tồn tại tại thời điểm phát hành), nhưng thay vào đó là N3000 (từ), thì không phải gọi cho những bổ sung này quá tải. Do đó, nó khắc nghiệt để đổ lỗi VC++ quá nhiều ở đây ...
Trong mọi trường hợp, chỉ một số ít các cuộc gọi, không có gì sai với việc sử dụng một dàn diễn viên để giải quyết sự mơ hồ tự hỏi:
void SentryManager::add(std::string& name, std::shared_ptr<Sentry>) {
name += std::to_string(static_cast<long long>(counter));
}
hoặc, nếu có sử dụng nặng của std::to_string
trong codebase của bạn, hãy viết một vài giấy gói và sử dụng những thay - Bằng cách này, không đúc gọi tại chỗ là cần thiết:
#include <type_traits>
#include <string>
template<typename T>
inline
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, std::string>::type
to_string(T const val) {
return std::to_string(static_cast<long long>(val));
}
template<typename T>
inline
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, std::string>::type
to_string(T const val) {
return std::to_string(static_cast<unsigned long long>(val));
}
template<typename T>
inline typename std::enable_if<std::is_floating_point<T>::value, std::string>::type
to_string(T const val) {
return std::to_string(static_cast<long double>(val));
}
// ...
void SentryManager::add(std::string& name, std::shared_ptr<Sentry>) {
name += to_string(counter);
}
Tôi không thể kiểm tra xem VC++ 2010 thành công hay thất bại với việc sử dụng SFINAE ở trên; nếu nó không thành công, sau đây - sử dụng thẻ công văn thay vì SFINAE - nên compilable (nếu có khả năng chưa rõ ràng):
#include <type_traits>
#include <string>
namespace detail {
template<typename T> // is_float is_unsigned
inline std::string to_string(T const val, std::false_type, std::false_type) {
return std::to_string(static_cast<long long>(val));
}
template<typename T> // is_float is_unsigned
inline std::string to_string(T const val, std::false_type, std::true_type) {
return std::to_string(static_cast<unsigned long long>(val));
}
template<typename T, typename _> // is_float
inline std::string to_string(T const val, std::true_type, _) {
return std::to_string(static_cast<long double>(val));
}
}
template<typename T>
inline std::string to_string(T const val) {
return detail::to_string(val, std::is_floating_point<T>(), std::is_unsigned<T>());
}
Bạn có thể bao gồm thông báo lỗi thực tế và trình biên dịch & phiên bản bạn đang sử dụng (không thể tái sản xuất với GCC 4.5) hay không. – Mat
OK - xem chỉnh sửa. – pighead10