54

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 ++2010Expressを使用しています。

4

2 に答える 2

87

VC ++ 2010には、それぞれ、、、およびの3つのオーバーロードがあります。明らかstd::to_stringにこれらのいずれでもありません。また、1つの変換が別の変換(デモ)より優れているわけではないため、変換を暗黙的/明確に行うことはできません。long longunsigned long longlong doubleint

実際のC++11サポートに関しては、これはVC ++ 2010の標準ライブラリ実装の一部で失敗しています。C++11標準自体は、実際には([string.conversions] / 7)の9つのオーバーロードを要求します。std::to_string

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標準(リリース時点ではまだ存在していませんでした)ではなく、これらの追加のオーバーロードを必要としないN30002009年以降)に基づいていました。したがって、ここで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);
}

上記のSFINAEの使用で、VC++2010が成功するか失敗するかを確認できません。失敗した場合は、SFINAEの代わりにタグディスパッチを使用して、コンパイル可能である必要があります(明確性が低い可能性がある場合)。

#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>());
}
于 2012-05-19T15:51:53.617 に答える
11

あなたはC++ DR1261につまずきました。

'' 'と' 'の間があいまいなため、コード" int i; to_string(i);"はコンパイルに失敗します。を使用するためだけに、ユーザーがより大きな型に数値をキャストすることを期待するのは不合理に思えます。intlong longlong long unsignedto_string

提案された解決策は、さらに過負荷を追加することです。 GCCはこれをすでに実装しています; MSVCはそうではないと思います。

于 2012-05-19T15:57:18.680 に答える