std :: to_string - 超过重载函数的实例匹配参数列表 [英] std::to_string - more than instance of overloaded function matches the argument list
问题描述
计数器
是 int
void SentryManager :: add(std :: string name,std :: shared_ptr< Sentry>){
name = name + std :: to_string
}
停止此错误的最佳方法是什么?当我懒惰的时候,我只是做了 long long
(或某事),但我相信有一个更好的解决方法。
错误讯息:
sentrymanager.cpp(8):error C2668:'std :: to_string':重载函数的模糊调用
我使用Visual C ++ 2010 Express。
$在VC ++ 2010中,有三个重载 std :: to_string
,它们取 long long
, unsigned long long
和 long double
。显然, int
不是这些,没有一个转换比另一个更好(在线演示),因此转换不能隐式/明确。 在实际的C ++ 11支持,这是一个失败的VC ++ 2010的部分标准库实现– C ++ 11标准本身实际上要求 std :: to_string
(§21.5)的 9个重载:
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);
如果所有这些重载都存在,你显然不会有这个问题;然而,VC ++ 2010不是基于实际的C ++ 11标准(它在发布时尚未存在),而是基于N3000,它不是调用这些额外的重载。因此,这里很难指责VC ++ 太多...
在任何情况下,只有少数几个调用,没有什么错误使用转换自己解决歧义:
void SentryManager :: add(std :: string& name,std :: shared_ptr< ; Sentry>){
name + = std :: to_string(static_cast< long long>(counter));
}
或者,如果使用 std :: to_string
在你的代码库中,写几个封装,并使用它们–这样,不需要呼叫站点转换:
#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);
}
(我无法检查VC ++ 2010是否成功或失败,的SFINAE;如果失败,以下 - 使用标签分发而不是SFINAE - 应该是可编译的,如果可能不清楚:
#include< type_traits>
#include< string>
命名空间详细信息{
template< typename T>
inline std :: string
to_string(T const val,std :: false_type / * is_float * /,std :: false_type / * is_unsigned * /){
return std :: to_string(static_cast< long long>(val));
}
template< typename T>
inline std :: string
to_string(T const val,std :: false_type / * is_float * /,std :: true_type / * is_unsigned * /){
return std :: to_string(static_cast< unsigned long long>(val));
}
template< typename T,typename _>
inline std :: string
to_string(T const val,std :: true_type / * is_float * /,_){
return std :: to_string(static_cast< long double> );
}
} //命名空间细节
模板< typename T>
inline std :: string to_string(T const val){
return detail :: to_string(val,std :: is_floating_point< T>(),std :: is_unsigned< T&
}
)
counter
is an int
void SentryManager::add(std::string name,std::shared_ptr<Sentry>){
name = name + std::to_string(counter);
}
What would be the best way to stop this error? When I was being lazy I just made the int long long
(or something), but I'm sure there is a better way of solving this.
Error message:
sentrymanager.cpp(8): error C2668: 'std::to_string' : ambiguous call to overloaded function
I am using Visual C++ 2010 Express.
In VC++ 2010 there are three overloads of std::to_string
that take long long
, unsigned long long
, and long double
, respectively. Clearly, int
is none of these, and no one conversion is better than another (online demo), so the conversion cannot be done implicitly/unambiguously.
In terms of real C++11 support, this is a failing on the part of VC++ 2010's standard library implementation – the C++11 standard itself actually calls for nine overloads of std::to_string
(§21.5):
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);
Had all of these overloads been present, you obviously wouldn't have this problem; however, VC++ 2010 wasn't based on the actual C++11 standard (which did not yet exist at the time of its release), but rather on N3000, which did not call for these additional overloads. Consequently, it's harsh to blame VC++ too much here...
In any case, for only a handful of calls, there's nothing wrong with using a cast to resolve the ambiguity yourself:
void SentryManager::add(std::string& name, std::shared_ptr<Sentry>) {
name += std::to_string(static_cast<long long>(counter));
}
Or, if there's heavy usage of std::to_string
in your codebase, write a few wrappers and use those instead – this way, no call-site casting is needed:
#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);
}
(I can't check whether VC++ 2010 succeeds or fails with the above usage of SFINAE; if it fails, the following – using tag dispatch instead of SFINAE – should be compilable, if potentially less clear:
#include <type_traits>
#include <string>
namespace detail {
template<typename T>
inline std::string
to_string(T const val, std::false_type /*is_float*/, std::false_type /*is_unsigned*/) {
return std::to_string(static_cast<long long>(val));
}
template<typename T>
inline std::string
to_string(T const val, std::false_type /*is_float*/, std::true_type /*is_unsigned*/) {
return std::to_string(static_cast<unsigned long long>(val));
}
template<typename T, typename _>
inline std::string
to_string(T const val, std::true_type /*is_float*/, _) {
return std::to_string(static_cast<long double>(val));
}
} // namespace detail
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>());
}
)
这篇关于std :: to_string - 超过重载函数的实例匹配参数列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!