std :: to_string - 超过重载函数的实例与参数列表匹配

时间:2012-05-19 11:16:08

标签: c++ visual-studio-2010 visual-c++ c++11

counterint

void SentryManager::add(std::string name,std::shared_ptr<Sentry>){
    name = name + std::to_string(counter);
}

什么是阻止此错误的最佳方法?当我懒惰的时候我刚刚创建了int long long(或其他东西),但我确信有更好的解决方法。

错误讯息:

sentrymanager.cpp(8): error C2668: 'std::to_string' : ambiguous call to overloaded function

我正在使用Visual C ++ 2010 Express。

2 个答案:

答案 0 :(得分:86)

在VC ++ 2010中,std::to_string有三个重载分别占用long longunsigned long longlong double - 显然int不是这些,并且没有一个转换比另一个转换(demo)更好,因此无法隐式/明确地进行转换。

就真正的C ++ 11支持而言,这是VC ++ 2010标准库实现的一个失败 - C ++ 11标准本身实际上要求{em> 9的 9 重载([string.conversions] / 7):

std::to_string

如果存在所有这些重载,你显然不会有这个问题;但是,VC ++ 2010并非基于实际的C ++ 11标准(在发布时尚未存在),而是基于N3000(来自 2009 ), 调用这些额外的重载。因此,在这里谴责VC ++ 太多是很苛刻的......

在任何情况下,对于少数几次调用,使用强制转换来解决模糊性并没有错:

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);

或者,如果您的代码库中大量使用void SentryManager::add(std::string& name, std::shared_ptr<Sentry>) { name += std::to_string(static_cast<long long>(counter)); } ,请编写一些包装并使用它们 - 这样就不需要调用站点转换:

std::to_string

我无法检查VC ++ 2010是否成功使用SFINAE;如果失败,以下 - 使用标签发送而不是SFINAE - 应该是可编译的(如果可能不太清楚):

#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);
}

答案 1 :(得分:10)

你绊倒C++ DR 1261,部分读取

  

代码“int i; to_string(i);”无法编译,因为“int”与“long long”之间的“long long unsigned”不明确。期望用户将数字转换为更大的类型只是为了使用to_string

似乎是不合理的

建议的解决方案是增加更多重载。 GCC has implemented this already;我猜MSVC没有。