1

I stumbled on a weird compiler error when working on one of my projects. I manage to reproduce the error with this small code

#include <iostream>

class base
{
private:
    char f;
public:
    char get_char()
    {
    return f;
    }
    base(char f)
    {
    this->f = f;
    }
};


class derived : public base
{
private:
    std::string msg;
public:
    const std::string &get_message() const
    {
    return msg;
    }
    derived(const std::string& msg) : base(msg.c_str()[0])
    {
    this->msg = msg;
    }
};

void print_base(base &base_obj)
{
    std::cout << base_obj.get_char() << std::endl;
}


const char *input = "Hello World!";

int main(int argc, char* argv[])
{
    // This line compiles
    //derived d = derived(std::string(argv[0]));

    // This also works
    //derived d(argv[0]);

    // This line gives compiler error (see below)
    derived d(std::string(argv[0]));

    print_base(d);

    return 0;
}

The line that does not work gives me compiler error:

ain.cpp: In function ‘int main(int, char**)’:
main.cpp:50:17: error: invalid initialization of non-const reference of type ‘base&’ from an rvalue of type ‘derived (*)(std::string*) {aka derived (*)(std::basic_string<char>*)}’
     print_base(d);
             ^
main.cpp:34:6: error: in passing argument 1 of ‘void print_base(base&)’
 void print_base(base &base_obj)

Why doesn't the second way of initializing compile?

ADDITIONAL INFO:

Compiler: g++

bofjas
  • 1,186
  • 7
  • 19

3 Answers3

3
derived d(std::string(argv[0]));

Declares a function named d that takes a pointer to std::string as an argument. This is one of the most vexing parses, since it does something it may not look like it should do. It is the same as

derived d(std::string* argv);

To fix this, leave out the explicit string construction, or use braces or double parentheses.

derived d(argv[0]);

or

derived d{std::string(argv[0])}; // C++11

or

derived d((std::string(argv[0])));    
uk4321
  • 1,028
  • 8
  • 18
3

The clue in the error message is:

from an rvalue of type ‘derived (*)(std::string*)

and indicates you're suffering from the C++ most vexing parse

Community
  • 1
  • 1
SteveLove
  • 3,137
  • 15
  • 17
2
derived d(std::string(argv[0])); //function declaration (your code!)

is equivalent to this:

derived d(std::string argv[0]);

which is a function declaration (not object declaration).

Use uniform-initialization-syntax to avoid such problem:

derived d { std::string(argv[0]) }; //object declaration

Hope that helps.

Nawaz
  • 353,942
  • 115
  • 666
  • 851