开发者

Ambiguous template error adding std::string to uint in Visual C++

开发者 https://www.devze.com 2023-01-17 21:42 出处:网络
I\'m getting the following error when I compile the following code on Visual Studio 2008 / Windows SDK 7

I'm getting the following error when I compile the following code on Visual Studio 2008 / Windows SDK 7

const UINT a_uint;
UINT result;

throw std::runtime_error( std::string("we did ") + a_uint +
                          " and got " + result );

Ironically, I ended up with thi开发者_运维技巧s result:

error C2782: 'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(
                 const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem
             )' : template parameter '_Elem' is ambiguous

Can someone explain why the error message doesn't explain the real problem (that there is no operator for +ing ints to strings)?


You can reduce that to this

template<typename T>
void f(T, T);

int main() {
 f('0', 0); // is T int or char?
}

You try to add an unsigned int to a string. That does not make sense, and the std::string class does not need to take any precautions to add implicit conversions to char here because that would hide such potential programming bugs.

Try to convert the unsigned int to std::string into a decimal/hexadecimal/octal/etc form and then concatenate (you can do that using std::ostringstream or boost::lexical_cast) or fix the bug in other ways you see fit.


Use stringstream (defined in the sstream header) to compose the error message:

std::stringstream ss;
ss << "we did " << a_uint << " and got " << result;
throw std::runtime_error(ss.str());


To a std::string, you can only add other std::strings, ASCIIZ text at an address specified by a const char*, and individual char-acters.

To concatenate other types, you can:

  • use a stream:

    std::ostringstream oss; oss << "we did " << a_uint << " and got " << result; throw std::runtime_error(oss.str());

  • convert it first to a string representation:

    throw std::runtime_error(std::string("we did ") + boost::lexical_cast(a_uint) + " and got " + boost::lexical_cast(result));

You might reasonably wonder why C++ doesn't provide operator+(std::string&, X&) for X in { short, int, long, long long, float, double, unsigned short etc. }, or even:

template <typename T>
std::string operator+(std::string& s, T& t)
{
    std::ostringstream oss;
    oss << t;
    return s + oss.str();
}

In many cases it would be convenient. But streams are more powerful as you can tune the padding width and character, floating point precision etc.. Further, char is the 8-bit integer type, so how could the compiler know whether to append a single character with that ASCII value (e.g. 'A' for 65), or an ASCII representation of the numeric ASCII value "65"? (Currently it doesn't handle any ints, so treating it as a single ASCII char isn't confusing). Or should it work for >=16 bit numbers but not 8? That would make it impossible to resize variables to/from 8-bit ints without having to do a complex impact analysis to see which string operations needed to be rewritten. It's also good practice to minimise dependencies: some small but perhaps significant percentage of translation units using string may not currently have to include (and hence spend time parsing) (and hence ostream etc), and in general cyclic dependencies are a "code smell" and frustrate testability (string depends on ostringstream depends on string...).


Next time please post the full error (it should continue "with [ _Elem = ], could be one of [list of ambiguous overloads]").

The problem is that you concatenate UINT with a std::string. This is not a valid operation, you first have to convert the UINT to a std::string (search Google for handy functions). The compiler is trying to do its best and tries to match some of the std::string operators to the UINT. Apparently, it finds some matches but these certainly aren't what you are looking for.

0

精彩评论

暂无评论...
验证码 换一张
取 消