c ++ 0x隐式转换为非标量类型

时间:2014-05-02 10:25:19

标签: c++ c++11 reference rvalue

编辑:编译器版本已修复。

我尝试了c ++ 11的新功能,虽然我有Ubuntu 12.04,其中包含gcc 4.6.3,因此只支持c ++ 0x。我对以下示例类以及它的构造函数,赋值运算符和其他运算符有一个大致的理解问题。

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;
};

我现在尝试使用以下

调用所有上述构造函数和运算符
// 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

正如我发现的那样,由于行

而无法编译
exception e2 = "This is again the move constructor"; // move construct

这似乎是一个非法移动构造函数调用。据我所知,char const []被隐式转换为string&amp;&amp;就像在

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

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

为什么标准不允许这样做?

我得到的错误是:

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

我可以通过将行更改为

来轻松解决此错误
exception e2 = string("This is again the move constructor"); // move construct

2 个答案:

答案 0 :(得分:2)

这样做的原因是,为了从exception消息创建const char[],编译器必须调用两个隐式转换(一个来自{{1}到const char[],然后到string),但C ++标准(包括C ++ 11)只允许一个。

有关详细信息,请参阅this question,包括C ++标准的章节和节。

答案 1 :(得分:1)

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

首先,您展示的代码没有移动构造函数。移动构造函数将是接受exception&&的构造函数。不会为您生成默认移动构造函数,因为您已明确声明了析构函数。

上面的行尝试做的是调用默认的复制构造函数。要做到这一点,它必须从字符串文字转换为异常,这在一个步骤中是不可能的。

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

现在这只需要一次转换。但它会调用默认的复制构造函数而不是string&&构造函数。