Question

EDIT: Compiler version fixed.

I'm trying out the new features of c++11 although I have Ubuntu 12.04 which includes gcc 4.6.3, thus only supporting c++0x. I have a general understanding problem with the following example class and it's constructors, assign operators and other operators.

class exception : public std::exception {
  public:
    exception(string& inMessage) throw() : message(inMessage) {
      std::cout << "exception(string& inMessage): '" << message << "'" << std::endl;
    }
    exception(string&& inMessage) throw() : message(std::move(inMessage)) {
      std::cout << "exception(string&& inMessage): '" << message << "'" << std::endl;
    }
    ~exception() throw() { }
    exception& operator =(string&& inMessage) {
      std::swap(message, inMessage);
      std::cout << "operator =(string&& inMessage): '" << message << "'" << std::endl;
      return *this;
    }
    exception& operator =(string& inMessage) {
      message = inMessage;
      std::cout << "operator =(string& inMessage): '" << message << "'" << std::endl;
      return *this;
    }
    exception& operator <<(string&& inMessage) {
      message += inMessage;
      std::cout << "operator <<(string&& inMessage): '" << message << "'" << std::endl;
      return *this;
    }
    exception& operator <<(string& inMessage) {
      message += inMessage;
      std::cout << "operator <<(string& inMessage): '" << message << "'" << std::endl;
      return *this;
    }
    char const* what() const throw() {
      return message.c_str();
    }
  private:
    string message;
};

I'm now trying to invoke all the above constructors and operators with the following

// constructors:
exception e1("This is the move constructor"); // move construct

exception e2 = "This is again the move constructor"; // move construct

string s("This is a lvalue string");
exception e3(s); // copy construct

// assignment:
e2 = "This is the move assignment"; // move assign

e2 = s; // copy assign

// operator <<:
e3 << "This is the rvalue reference operator >>"; // rvalue ref

e3 << s; // lvalue ref

e3 << std::move(s); // forced rvalue ref

As I found out, this won't compile because of the line

exception e2 = "This is again the move constructor"; // move construct

which seems to be an illegal move constructor invoke. As I understand, the char const[] is implicitly converted to string&& just as in

e3 << "This is the rvalue reference operator >>"; // rvalue ref

or

e2 = "This is the move assignment"; // move assign

Why does the standard not allow this?

The error I'm getting is this:

main.cpp:40:18: error: conversion from ‘const char [33]’ to non-scalar type ‘exception’ requested

I can easily solve this error by changing the line into

exception e2 = string("This is again the move constructor"); // move construct
Was it helpful?

Solution

The reason for this is that in order to create an exception from your const char[] message, the compiler would have to invoke two implicit conversions (one from const char[] to string, and thence to an exception), but the C++ standard (C++11 included) only allows one.

See this question for more detail including chapter and verse from the C++ standard.

OTHER TIPS

exception e2 = "This is again the move constructor"; // move construct

First of all, the code you've shown doesn't have a move constructor. A move constructor would be one that accepts exception&&. A default move constructor isn't being generated for you, because you've explicitly declared a destructor.

What the line above tries to do is invoke your default copy constructor. To do this, it has to convert from a string-literal to an exception, which isn't possible in a single step.

exception e2 = string("This is again the move constructor"); // move construct

Now this only requires one conversion. But it will call your default copy constructor instead of the string&& constructor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top