c++stringreturn-value-optimization

C++ no conversion from const char [n] to const char *?


Code:

#include <iostream>
#include <cstring>

class MyString
{
  public:
  MyString() {
    std::cout << "1";
  }
  explicit MyString(const char *str) {
    std::cout << "2";
  }
};

int main()
{
  MyString str1 = MyString("abcde");
  MyString str2("abcde");
  MyString str3 = "abcde";

  return 0;
}

str1 and str2 are created just fine, printing out 2. But when I run it with str3 I get the following error message:

Compilation failed due to following error(s).main.cpp: In function ‘int main()’:
main.cpp:19:19: error: conversion from ‘const char [6]’ to non-scalar type ‘MyString’ requested
19 |   MyString str3 = "abcde";

Aren't all 3 lines supposed to call the second constructor, because of RVO? Or is it because I'm using a non-RVO compiler? I tried it both on CMake and gcc and both have the same error message.

I tried creating an operator= and still got the same error, so it clearly isn't from RVO:

#include <iostream>
#include <cstring>

class MyString
{
  public:
  MyString() {
    std::cout << "1";
  }
  explicit MyString(const char *str) {
    std::cout << "2";
  }
  MyString& operator=(const char *str) {
    std::cout << "3";
    return *this;
  }
};

int main()
{
  MyString str1 = MyString("abcde");
  MyString str2("abcde");
  MyString str3 = "abcde";

  return 0;
}

I searched around for quite a bit, but couldn't find an answer.


Solution

  • MyString str3 = "abcde"; performs copy initialization, which doesn't work with explicit constructors. More formally:

    [...] if T is a class type, and the cv-unqualified version of the type of other is not T or derived from T, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution.

    Here T is a class type (MyString) and other is not of a class type (const char[6]), and there is no user-defined conversion sequence because one cannot contain explicit constructors.