thedarkside ofthemoon
thedarkside ofthemoon

Reputation: 2291

C++ Exception constructor error because of returned string

I have some problem with a returned string: I have a function that returns a string:

std::string foo(const std::string& paramIn)
{
  return ("My message" + paramIn);
}

and I have an exception class:

class MyException : public std::exception
{
private:
  std::string m_msg;

public:
  MyException(std::string& msg) : m_msg(msg) {}
  virtual ~MyException() throw() {}

  virtual const char* what() const throw()
  {
    return m_msg.c_str();
  }
};

The problem appears when I throw an MyException that takes as argument the foo function's return:

throw MyException(foo("blabla"));

It says:

/home/me/my_proj/main.cpp: In member function ‘std::string ConfigFile::getClassifierExtractorType()’:
/home/me/my_proj/main.cpp:79:96: error: no matching function for call to ‘MyException::MyException(std::string)’
     throw MyException(foo("blabla"));
                                    ^
/home/me/my_proj/main.cpp:79:96: note: candidates are:
In file included from /home/me/my_proj/main.hpp:5:0,
                 from /home/me/my_proj/main.cpp:1:
/home/me/my_proj/CMyExceptions.hpp:38:3: note: MyException::MyException(std::string&)
   MyException(std::string& msg) : m_msg(msg) {}
   ^
/home/me/my_proj/CMyExceptions.hpp:38:3: note:   no known conversion for argument 1 from ‘std::string {aka std::basic_string<char>}’ to ‘std::string& {aka std::basic_string<char>&}’
/home/me/my_proj/CMyExceptions.hpp:32:7: note: MyException::MyException(const MyException&)
 class MyException : public MyIOException
       ^

If I just put the returned string in a variable:

std::string msg = foo("blabla");
throw MyException(msg);

It works fine (no errors), why? How to fix this?

Upvotes: 0

Views: 194

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 477560

Rvalues do not bind to non-const lvalue references. Change your constructor:

MyException(std::string const & msg)
//                      ^^^^^

In modern C++, you could even take the string by value:

MyException(std::string msg) noexcept : m_msg(std::move(msg)) { }

This has the added advantage that your exception class can be constructed without itself throwing exceptions, unlike your original code.

Upvotes: 5

Related Questions