9
votes

I'm learning C++. I regularly get errors that look like this

/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/basic_string.h:1458: instantiated from 'static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct_aux(_InIterator, _InIterator, const _Alloc&, std::__false_type) [with _InIterator = std::istream_iterator, std::allocator >, char, std::char_traits, int>, _CharT = char, _Traits = std::char_traits, _Alloc = std::allocator]'

How do I make sense of this so that I can at least have some place to search for a solution?

In case you're interested, the original code is:

#include <iostream>
#include <fstream>
#include <string>
#include <iterator>

using namespace std;

int main(int argc, char **argv) {
    string fileName = "example.txt";
    ifstream ifile(fileName.c_str());

    istream_iterator<string> begin(ifile);
    istream_iterator<string> end;

    string s(begin,end);
    cout << s;
}
5

5 Answers

6
votes

This is not the whole error, just a description of one instantiation.

Basically you care about:

1) which line in your code triggered the error (string s(begin,end);)

2) what error did it result in (e.g cannot convert 'const std::basic_string<char, std::char_traits<char>, std::allocator<char> >' to 'char' in assignment) and where

3) you might compare what the compiler is saying the template parameters are, and what you assume them to be.

It probably takes some experience not to be scared of the errors, and it certainly helps to know the library well.

In this case the cause is that the string's constructor is expecting a range of characters, but you are passing a range of strings.

3
votes

Comeau has much much friendlier compiler, check it out online: http://www.comeaucomputing.com/tryitout/

for example, this is the error:

Comeau C/C++ 4.3.10.1 (Oct  6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ C++0x_extensions

"string", line 1175: error: no suitable conversion function from
          "const std::string" to "char" exists
      push_back(*__first);
                ^
          detected during instantiation of "std::basic_string<_CharT, _Traits,
                    _Alloc> &std::basic_string<_CharT, _Traits,
                    _Alloc>::append(_InputIter, _InputIter,
                    std::input_iterator_tag) [with _CharT=char,
                    _Traits=std::char_traits<char>,
                    _Alloc=std::allocator<char>,
                    _InputIter=std::istream_iterator<std::string, char,
                    std::char_traits<char>, ptrdiff_t>]" at line 624

1 error detected in the compilation of "ComeauTest.c".

which leads me to assume that constructor expects char iterarator rather than iterator over strings (as in many strings):

istream_iterator<char> begin(ifile);
istream_iterator<char> end;
2
votes

You actually omitted the key parts of the error message. You get two duplicate errors in g++ 4.2. The key parts are: /path/basic_string.tcc:103: error: cannot convert 'const std::basic_string<char, std::char_traits<char>, std::allocator<char> >' to 'char' in assignment and str_iter_test.C:15: instantiated from here.

The first part means that it couldn't convert from string to char, and the second part says on which line the error occurred, in this case string s(begin,end);.

In this case, your iterators should iterate over char not string:

istream_iterator<char> begin(ifile);
istream_iterator<char> end;
1
votes

The particular error message you show should only be part of the error issued by g++. The full error should look something closer to the following (I've shortened the paths, and this output is from 4.1.2):

basic_string.tcc: In static member function 'static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct(_InIterator, _InIterator, const _Alloc&, std::input_iterator_tag) [with _InIterator = std::istream_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, char, std::char_traits<char>, int>, _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]':
basic_string.h:1449:   instantiated from 'static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct_aux(_InIterator, _InIterator, const _Alloc&, __false_type) [with _InIterator = std::istream_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, char, std::char_traits<char>, int>, _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'
basic_string.h:1464:   instantiated from 'static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct(_InIterator, _InIterator, const _Alloc&) [with _InIterator = std::istream_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, char, std::char_traits<char>, int>, _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'
basic_string.tcc:241:   instantiated from 'std::basic_string<_CharT, _Traits, _Alloc>::basic_string(_InputIterator, _InputIterator, const _Alloc&) [with _InputIterator = std::istream_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, char, std::char_traits<char>, int>, _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'
t.cpp:16:   instantiated from here
Line 101: error: cannot convert 'const std::basic_string<char, std::char_traits<char>, std::allocator<char> >' to 'char' in assignment
compilation terminated due to -Wfatal-errors.

That's not much friendlier, is it? :-) The useful lines in the error are the lines at the end, not the lines at the beginning. The error message is issued in reverse order: the first error is the actual error, then the subsequent lines give you breadcrumbs through the source showing how the compiler got there. The last line shows where in your source the error was:

t.cpp:16:   instantiated from here
Line 101: error: cannot convert '
    const std::basic_string<char, std::char_traits<char>, std::allocator<char> >' to 
    'char' in assignment

In my example file, t.cpp:16 is the following line:

string s(begin,end);

If you comment out that line (and the line following it that uses s), you'll find that your source compiles without error.

At this point, it should be fairly clear that you are using the std::string constructor incorrectly, which means you are passing it the wrong types of arguments. You are giving it something that has a std::string (that's what std::basic_string<char> is) and it is expecting something that has a char.

If you consult the documentation for std::string, you'll find that it does have a constructor that looks like:

template <typename InputIterator>
string(InputIterator first, InputIterator last);

Those input iterators allow you to create a string from a range of characters. You, however, are passing a range of std::strings to the constructor. If you change your istream_iterator<string>s to istream_iterator<char> that should fix the error.