Avinash
Avinash

Reputation: 13277

error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const std::string' (or there is no acceptable conversion)

I am really confused on why I am getting following compilation error. Microsoft Visual Studio Compiler.

error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const std::string' (or there is no acceptable conversion)

#include <stdio.h>
#include <iostream>
#include <sstream>
#include <iterator>

class MyException {
public:
    MyException(    std::string message, 
                        int line = 0) : m_message(message),
                                        m_line(line) {}
    const char* what() const throw(){
        if ( m_line != 0 ) {
            std::ostringstream custom_message;
            custom_message << "Parsing Error occured at ";
            custom_message << m_line << " Line : ";
            custom_message << m_message;        
            m_message = custom_message.str();
        }
        return m_message.c_str();
    }
private:
    std::string m_message;
    int m_line;
};
int main(int argc, char **argv) {
    try {
        // do something
    }catch(MyException &e){
        std::cout << e.what();
    }
}

Error is coming at line m_message = custom_message.str();

Upvotes: 10

Views: 29846

Answers (4)

wilx
wilx

Reputation: 18268

See the declaration of the what() function, it is marked const (the second const on the line). That means that it cannot alter any member variables, in your case the m_message string. That is why you get the error.

Now, how do you fix it?

Your code is wrong, your what() function will prepend the "Parsing Error occured at " etc. text each time you invoke the what() function. So, instead of doing that having to modify the m_message member, I suggest that you format the entire message in the ctor of the class:

MyException(std::string message, int line = 0)
{
    if (line != 0)
    {
        std::ostringstream custom_message;
        custom_message << "Parsing Error occured at ";
        custom_message << line << " Line : ";
        custom_message << message;        
        m_message = custom_message.str();            
    }
    else
        m_message = message;
}

Upvotes: 0

AnT stands with Russia
AnT stands with Russia

Reputation: 320797

You are trying to assign to MyException::m_message inside a const-qualified method MyException::what(). Inside such what() the entire *this object is considered to be const, which means that m_message member is also const. You can't assign anything to a const-qualified std::string object, since std::string's assignment operator requires a modifiable (i.e. a non-const one) object on the left-hand side. You are supplying a const one.

If you really want to be able to modify the m_message inside what(), you should declare it as mutable member of the class (in this case it appears to be a good idea). Or use some other approach.

As @john noted, in your specific case it makes more sense to actually build m_message in constructor instead of postponing it till what(). I don't really understand why you'd even want to rebuild your m_message every time you call what(). Unless your m_line is expected to change somehow from one call to what() to another, there's really no need to do it every time.

Upvotes: 3

john
john

Reputation: 88092

You declare the method as const

const char* what() const throw(){

but then you try to change the object

m_message = custom_message.str();

so you get an error.

What you should do instead is construct the custom message in the constructor.

class MyException {
public:
    MyException(const std::string& message, int line = 0) : 
        m_message(message), m_line(line) {
        if ( m_line != 0 ) {
            std::ostringstream custom_message;
            custom_message << "Parsing Error occured at ";
            custom_message << m_line << " Line : ";
            custom_message << m_message;        
            m_message = custom_message.str();
        }
    }
    const char* what() const throw(){
        return m_message.c_str();
    }
private:
    std::string m_message;
    int m_line;
};

Also I changed your code to pass the std::string by reference, which is usual practice.

Upvotes: 22

Seb Holzapfel
Seb Holzapfel

Reputation: 3873

In addition to the other answers;

You're not including the <string> header, which may be the cause of a problem later.

Something that used to get me a lot is that some std:: headers include others, which allows you to use a class, but maybe only with limited functionality because the std:: headers that they include are the bare minimum that is needed for that file to run. This is quite an annoyance because sometimes you declare a std:: class such as string and you haven't included the header, the definition will be fine but everything else may or may not work - leading you to a lot of debugging because the definition worked fine.

Upvotes: 1

Related Questions