Вопрос по visual-c++, c++, visual-studio-2010, c++11 – std :: to_string - более чем экземпляр перегруженной функции соответствует списку аргументов

51

counter являетсяint

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

Как лучше всего остановить эту ошибку? Когда я был ленивым, я просто сделал интlong long (или что-то в этом роде), но я уверен, что есть лучший способ решения этой проблемы.

Сообщение об ошибке:

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

Я использую Visual C ++ 2010 Express.

Не могли бы вы включить фактическое сообщение об ошибке и какой компилятор & amp; версия, которую вы используете (не воспроизводится с помощью GCC 4.5). Mat
Хорошо, смотрите редактирование. pighead10

Ваш Ответ

2   ответа
86

std::to_string что взятьlong long, unsigned long long, а такжеlong doubleсоответственно & # x2013; явноint нет ни одного из них, и ни одно обращение не лучше другого (демонстрация), поэтому преобразование не может быть выполнено неявно / однозначно.

С точки зрения реальной поддержки C ++ 11, это ошибка со стороны реализации стандартной библиотеки VC ++ 2010 & # x2013; сам стандарт C ++ 11 фактически требуетnine перегрузки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);

Если бы присутствовали все эти перегрузки, у вас, очевидно, не было бы этой проблемы; однако VC ++ 2010 был основан не на фактическом стандарте C ++ 11 (который еще не существовал на момент его выпуска), а скорее наN3000 (от2009), который делаетnot призыв к этим дополнительным перегрузкам. Следовательно, винить VC ++ суровоtoo много здесь ...

В любом случае, только для нескольких звонков нет ничего плохого в использовании приведения для самостоятельного устранения неоднозначности:

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

Или, если интенсивно используетсяstd::to_string в своей кодовой базе напишите несколько оберток и используйте их вместо & # x2013; таким образом, не требуется кастинг колл-сайтов:

#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 выше; если это не удается, следующее & # x2013; использование отправки тегов вместо SFINAE & # x2013; должен быть компилируемым (если потенциально менее понятным):

#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>());
}
FYIg++ версия 4.4.7 в CentOS-6 также имеет ту же проблему (и также имеет тот же период времени, что и упомянутый выше компилятор MSVC).
Сообщение о дефекте 1261 произошло в 2009 году; Я думаю, что разумно обвинять Microsoft вlittle для медленного движения, по крайней мере.
Все перегрузки присутствуют в бета-версии Visual C ++ 11. Это на самом деле не является ошибкой реализации стандартной библиотеки: некоторые перегрузки были добавлены в C ++ 11after Visual C ++ 2010 был выпущен.
@Zack: Ну, никто никогда не обвинял MS в следовании лучшим практикам ...; -]
Выбор черновой версии стандарта для реализации и невнимание к исправлениям после этого - это не то, что я бы назвал лучшей практикой.The IE team does this too и это бесит.
10

C ++ DR 1261, который читает частично

The code "int i; to_string(i);" fails to compile, as 'int' is ambiguous between 'long long' and 'long long unsigned'. It seems unreasonable to expect users to cast numbers up to a larger type just to use to_string.

Предлагаемое решение заключается в добавлении дополнительных перегрузок.GCC уже реализовал это; Я предполагаю, что MSVC не имеет.

Резолюция была включена в окончательный стандарт C ++ 11. Visual C ++ 11 Beta включает в себя все перегрузки.

Похожие вопросы