IT이야기

std :: to_string-오버로드 된 함수의 인스턴스가 인수 목록과 일치합니다.

cyworld 2021. 4. 5. 21:14
반응형

std :: to_string-오버로드 된 함수의 인스턴스가 인수 목록과 일치합니다.


counter 이다 int

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를 사용하고 있습니다.


VC ++ 2010에는 각각 ,, std::to_string를 취하는 세 가지 오버로드 가 있습니다 long long. 분명히 이들 중 어느 것도없고 어떤 변환도 다른 것보다 낫지 않습니다 ( demo ). 따라서 변환은 암시 적으로 / 명백하게 수행 될 수 없습니다.unsigned 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 표준 (출시 당시 아직 존재하지 않았던)이 아니라 N3000 ( 2009 년부터 )을 기반으로 하여 이러한 추가 오버로드를 요구 하지 않습니다 . 결과적으로 여기에서 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>());
}

부분적으로 읽는 C ++ DR 1261 이상으로 넘어 갔습니다 .

int i; to_string(i);' int'이 (가) ' long long'와 ' long long unsigned' 사이에 모호 하므로 " " 코드 가 컴파일되지 않습니다 . 사용자가 단지 사용하기 위해 더 큰 유형으로 숫자를 캐스팅하길 기대하는 것은 비합리적으로 보입니다 to_string.

제안 된 해결책은 더 많은 과부하를 추가하는 것입니다. GCC는 이미 이것을 구현했습니다 . MSVC는 그렇지 않은 것 같습니다.

ReferenceURL : https://stackoverflow.com/questions/10664699/stdto-string-more-than-instance-of-overloaded-function-matches-the-argument

반응형