std :: to_string - 超过重载函数的实例匹配参数列表 [英] std::to_string - more than instance of overloaded function matches the argument list

查看:3738
本文介绍了std :: to_string - 超过重载函数的实例匹配参数列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

计数器 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆