0

My professor gave the following code:

Main.cpp

#include "state.h"
#include <string>
#include <iostream>

using namespace std;

int main(int argc, char const *argv[]){
    
    const int success = 0;
    string name;

    State x;
    
    State y = "s2"; // This doesn't compile
    State z = y;
    State* p = new State(z);

    x = *p;
    p->set_name("s3");
    delete p;
    x.get_name(name);

    std::cout << "Name of state x is " << name << std::endl;
    std::cout << "Total number of states is " << State::total_number_of_states() << std::endl;

    return success;
}

State.h

#ifndef STATE_H
#define STATE_H
#include <string>

using namespace std;


class State
{
private:
    string* name; // str pointer used for illustrative purposes
    static int number_of_states;

public:
    State();
    State(string state_name);
    State(const State& state); // Will basically be the copy constructor
    virtual ~State();
    State& operator=(const State& state); // Copy on equal
    void get_name(string& state_name) const; 
    void set_name(string state_name);
    static int total_number_of_states();
};
typedef State *State_pointer;

#endif

In g++ 4.8 on Ubuntu, I get the following error:

$ g++ example_main_1.cpp state.cpp
example_main_1.cpp: In function ‘int main(int, const char**)’:
example_main_1.cpp:14:12: error: conversion from ‘const char [3]’ to non-scalar type ‘State’ requested
  State y = "s2"; // This doesn't compile

I asked him about this in class, he said that this is valid C++ and that it should work. I've never seen this kind of class instantiation before, where it would have to convert from a string literal to a std::string then convert that to a State object.

My professor then went on to point out that there are other equivalent invocations that are extremely close:

State y = "s2";         // Does NOT compile
State y("s2");          // Does compile
State y = string("s2"); // Does compile

What's going on here? Why does the first not compile, but the second and third do? As well, is my professor mistaken in saying that the first statement should work? Or is it behavior that's compiler specific?

Community
  • 1
  • 1
lelandbatey
  • 193
  • 1
  • 1
  • 13
  • 4
    We need to see `state.h` – Daniel Frey Apr 24 '14 at 00:12
  • 2
    Only ONE user defined conversion can be applied. Look at http://stackoverflow.com/questions/867462/c-implicit-conversions – Jerry Jeremiah Apr 24 '14 at 00:15
  • And http://stackoverflow.com/questions/18895737/multiple-implicit-constructor-conversion – Jerry Jeremiah Apr 24 '14 at 00:18
  • 1
    'My professor then went on to point out that there are other equivalent invocations that are extremely close' Your professor sounds like C++ isn't their primary programming language if he/she thinks 'extremely close' has any bearing on validity at all in C++. If it's not exactly the same, it's not exactly the same. – aruisdante Apr 24 '14 at 00:32
  • `State y = "s2";` and `State y("s2");` are NOT equivalent. The first is "copy initialization" and the second is "direct initialization". – aschepler Apr 24 '14 at 00:48

1 Answers1

2

It looks like your State object has a constructor that takes string. The literal "s2" is type const char [3]. This is why you are receiving the error.

It is also compiler specific. The following code snippet works in VS2013, yet not G++:

struct State
{
    State(string s) { }
};

int main() {
    State s = "a";
}
yizzlez
  • 8,757
  • 4
  • 29
  • 44
  • Most likely, on whatever the professor's compiler settings, it has something that's promoting that to a string or some other non-standard upcast for the ``=`` operator – aruisdante Apr 24 '14 at 00:13
  • 2
    The literal `"s2"` is type `const char[3]`, as is clearly specified by the error message. Also, this answer does not explain why the literal should not work when the object takes a `string` – Mooing Duck Apr 24 '14 at 00:15
  • I realize why this is wrong. Before I even compiled the program, I thought it was peculiar and didn't think it was valid C++. Does anyone know why my professor might say it's valid C++ and should compile? Are there compiler flags that allow this (if so, what are they/where would I look to find that information)? Is there some other compiler that this would work under (I know he largely uses Red Hat on his own computers and might have tested it there)? – lelandbatey Apr 24 '14 at 00:18
  • Yes, it does. The implicit conversion from string literal (``const char*`` to ``string`` for the assignment operator is compiler specific if you haven't defined a ``const char*`` assignment op – aruisdante Apr 24 '14 at 00:18
  • It's weird that `State st("a")` works but `State st = "a"` doesn't, so it's understandable that some compilers might allow it as an extension. – ooga Apr 24 '14 at 00:22
  • Im wondering why nobody has posted the real explanation yet as it has been discussed on SO multiple times. Assignment would require **two** implicit conversions: char literal to `std::string` and std::string to State, while by construction through `State("a")` one only needs to convert the char literal to a `std::string` – Sebastian Hoffmann Apr 24 '14 at 00:32
  • Sure, but as clearly demonstrated by the links in the answer (and the fact that the professor believes it works, so it obviously must have compiled on their machine), some compilers bend the rules for the string-literal to string implicit conversion. And @JerryJeremiah did twice in the comments to the question. – aruisdante Apr 24 '14 at 00:34
  • @aruisdante yeah ofc, but that doesnt make the code any more standart-conformer. – Sebastian Hoffmann Apr 24 '14 at 00:36