2

Is there a way to convert a string to a custom class, for example if I have a class named Numb, but I want to declared it as a string with the = operator, can I overload it?

class Numb{
      std::string x;
};

int main(){
    Numb n = "32";
   //Creates a Numb and makes x = "32"
}
polmonroig
  • 937
  • 4
  • 12
  • 22
  • 1
    One way to do this is to add a constructor for `Numb`, so that you initialize the variable as `Numb n("32");` – Aziz May 22 '18 at 17:51
  • No , I don't want a constructor – polmonroig May 22 '18 at 17:55
  • 1
    Another way is to overload the assignment operator. So the answer to your original question is yes, you can overload it. There are many examples online on how to do so if you don't know the format. – Thomas Phan May 22 '18 at 17:57
  • "No , I don't want a constructor" your class has a constructor anyhow, why dont you want to use it? – 463035818_is_not_an_ai May 22 '18 at 18:07
  • Recommended reading: [What is a converting constructor in C++ ? What is it for?](https://stackoverflow.com/questions/15077466/what-is-a-converting-constructor-in-c-what-is-it-for) – user4581301 May 22 '18 at 18:26
  • 3
    @polmonroig "*No , I don't want a constructor*" - yes, you do. `Numb n = "32";` is identical to `Numb n("32");` They are both calls to the same constructor. So you would have to give `Numb` a constructor that accepts a `const char*` or a `std::string` as input, and then the constructor can assign that value to your `x` member. – Remy Lebeau May 22 '18 at 19:09

3 Answers3

2

Yes, you can using converting constructors. Something like:

struct A {
  A(std::string);
  // A is a struct, so str is public
  std::string str;
};

// implementation for converting constructor
A::A(std::string s) {
  str = s;
}

int main() {
  A my_a = std::string("hello");
  std::cout << my_a.str << '\n';
}

Sometimes you might not want this behavior. You can mark the constructor as explicit to disable it.

ehargitt
  • 71
  • 3
  • That seems to work, but how can I access the string "hello" after initializing? – polmonroig May 22 '18 at 18:01
  • @polmonroig Depends on your class. Maybe you expose your string as a public member? Maybe you create a getter? Maybe you overload `operator<<`? – ehargitt May 22 '18 at 18:05
  • but I mean, where is the string stored, you only declared a constructor, – polmonroig May 22 '18 at 18:06
  • @polmonroig i'll add to my answer – ehargitt May 22 '18 at 18:08
  • Ok, that makes sense, it is just what I wanted, thanks – polmonroig May 22 '18 at 18:12
  • You should change the constructor to accept the `std::string` by `const` reference, and get rid of the explicit conversion to `std::string` when passing in a string literal: `struct A { A(const std::string &); std::string str; }; ... A::A(const std::string &s) : str(s) {} ... A my_a = "hello";` – Remy Lebeau May 22 '18 at 19:18
2

You want to construct Numbs from a string literal. String literals are indistinguishable from type const char * String literals have type const char [N], which we can take as an argument by writing a function that accepts const char *.

To define a converting constructor with this behavior, just write a signature like that of a copy constructor, but instead of expecting an argument of the same type, expect an argument of type const char *. Its signature would look like Myclass(const char *);

Alternatively, you can copy or move construct from strings, but that would require doing Numb n = std::string { "32" }; or similar, to convert the string constant to a std::string.

Here is some sample code, in which main() returns 3. Here we also demonstrate what to do with the value: if we instead did Num n2 = std::string { "TRAP" };, the code would return 1. If we did Num n2 = std::string { "ANYTHING OTHER THAN TRAP" }; it would return 2.

#include <string>

struct Num {
    Num()
      : _val(2) {}

    Num(const std::string & str) {
        if (str == "TRAP") {
            _val = 1;
        } else {
            _val = 2;
        }
    }

    Num(const char * s) {
        _val = 3;
    }

    int _val;    
};

int main(void) {
    // Num n = std::string { "TRAP" }; // returns 1
    // Num n = std::string { "NOTTRAP" }; // returns 2
    Num n = "TRAP";
    return n._val;
}

https://godbolt.org/g/Lqwdiw

EDIT: Fix a mistake re the type system, take the string arg as & not &&, simplify example, update compiler explorer link.

Jack Meagher
  • 306
  • 1
  • 6
  • "String literals are indistinguishable from type `const char *`", well, not exactly. The type of a string literal is `const char [N]`, where `N` is the length of the string + 1 for the null terminator. So you *can* distinguish it from a `const char *`, but a `const char *` parameter can accept string literals – Justin May 22 '18 at 18:12
  • Sorry, I meant as the argument to a function; or am I mistaken, and there's a way to write a function that takes `const char [N]` as an argument and not `const char *`? – Jack Meagher May 22 '18 at 18:14
  • `const std::string&&`? A const r-value reference doesn't make sense – Chad May 22 '18 at 18:16
1

If you make x a public member, you can assign to it like this:

class Numb
{
    public:
        std::string x;
};

int main()
{
    Numb n{ "32" };
    Numb o = { "33" };
    n = { "34" };
    o.x = "35";
}
Sid S
  • 6,037
  • 2
  • 18
  • 24