0

So I have this little snippet where it thinks "abc" isn't a string but rather a const char [4], and so I can't assign it to my object. I've searched but haven't found any working solutions. Thanks in advance.

Tekst t = "abc";
Tekst Tekst::operator=(std::string& _text){
    return Tekst(_text);
}

Edit: since this is a major staple of almost every exercise in my Object Oriented Programming class, due to whatever reasons, we can't change anything that's in int main(), so changing Tekst t = "abc"; is a no-go.

Edit 2:Tekst(std::string _text) :text(_text) {};

Baltr
  • 3
  • 3
  • 1
    Your `operator=` doesn't look right. [Here's](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading) how to do it properly. –  Nov 12 '19 at 19:31
  • 4
    "_where it thinks "abc" isn't a string but rather a const char [4]_" It doesn't "think" that it is. `"abc"` is, in fact, of type `const char [4]`. Why do you think, that it should be `std::string`? – Algirdas Preidžius Nov 12 '19 at 19:32
  • 1
    Also, can you [edit your question](https://stackoverflow.com/posts/58825457/edit) and post the construction codes for `Tekst`? –  Nov 12 '19 at 19:32
  • How about providing `operator=(const char*)`? – acraig5075 Nov 12 '19 at 19:35
  • 1
    Also, related [Why not non-const reference to temporary objects?](https://stackoverflow.com/questions/13826897/why-not-non-const-reference-to-temporary-objects). TLDR: If you took the argument with `const` reference: `Tekst Tekst::operator=(std::string const& _text)` it would've compiled. – Algirdas Preidžius Nov 12 '19 at 19:36
  • Per edit 1, I'm not saying you should `main()` should be edited, I'm saying that the way you are implementing `operator=()` looks wrong. The link I shared shows how to do it properly (at least, I believe it should. There's a lot of information there, so maybe I should find it.) –  Nov 12 '19 at 19:37
  • Algirdas, it still compiles with the same error C2440. – Baltr Nov 12 '19 at 19:50

3 Answers3

4

Compiler doesn't think "abc" is a const char [4]. It is const char [4] and you think that it should be std::string, which is not correct. std::string can be implicitly constructed from const char *, but they are nowhere near the same.

You problem is actually that you're trying to bind a temporary to a non-const reference, which is impossible in C++. You should change the definition of your operator to

Tekst Tekst::operator=(const std::string& _text){
//                     ^ const here
    return Tekst(_text);
}

This will make your operator technically valid (as in, it compiles and there is no Undefined Behaviour). However, it does something very non intuitive. Consider the following:

Tekst t;
t = "abc";

In this example, t will not have any "abc" inside. The newly returned object is discarded and t is unchanged.

Most likely, your operator should look like this:

Tekst& Tekst::operator=(const std::string& _text){
    this->text = _text; //or however you want to change your object
    return *this;
}

Refer to the basic rules and idioms for operator overloading for more information about what is and what isn't expected in each operator.


On a semi-related note, you can have std::string from literal in C++14 and up:

#include <string>

using namespace std::string_literals;

int main() {
    auto myString = "abc"s; 
    //myString is of type std::string, not const char [4]
}

However, this wouldn't help with your case, because the main problem was binding a temporary to non-const reference.

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
0

Thanks to @Ted Lyngmo, "This should help: godbolt.org/z/j_RTHu", turns out all i had to do was add a separate constructor for taking in const char*

Tekst(const char* cstr) : Tekst(std::string(cstr)) {}

Baltr
  • 3
  • 3
  • That's not an answer to your question though. @Yksisarvinen's answer was. – Ted Lyngmo Nov 12 '19 at 20:05
  • I tried doing what he told me, it didn't work, so I guess I didn't figure it out well enough. – Baltr Nov 12 '19 at 20:10
  • 1
    The extra constructor is another converting constructor, just like `Tekst(const std::string&);` is. When using the `Tekst t = "abc";` syntax it can only try one implicit conversion (from `const char[4]` to `Tekst`) but since you had no such conversion constructor, you had to add it. – Ted Lyngmo Nov 12 '19 at 20:24
0

Tekst t = "abc"; is just syntax sugar for Tekst t("abc"); which means it does not even consider your operator= at all, it uses the class's constructor instead.

In order for Tekst t = "abc"; to compile, you need a constructor that accepts either a const char* or a const std::string& as input. However, the constructor you showed takes a std::string by value instead of by const reference, so it can't be used for string literals. So you need to add a new constructor for that:

Tekst(const char *_text) :text(_text) {};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770