3

If I write the following program, it works as I expect:

struct Foo {
    Foo (std::string x) { std::cout << x << std::endl; }
};

int main () { Foo("hello, world"); }

However, if I write a slightly different program, I get a compilation error:

struct Foo {
    Foo (std::string x) { std::cout << x << std::endl; }
};

std::string x("hello, world");

int main () { Foo(x); }

The error is:

prog.cc: In function 'int main()':
prog.cc:10:20: error: no matching function for call to 'Foo::Foo()'

The complete error can be seen on IDEONE.

Why does the error occur for the second program and not the first?

M.M
  • 138,810
  • 21
  • 208
  • 365
jxh
  • 69,070
  • 8
  • 110
  • 193

3 Answers3

12

You have declared a variable x with type Foo

struct Foo {
    Foo(){}
    Foo (std::string x) { std::cout << x << std::endl; }
    void test(){ std::cout << "test" << std::endl; };
};

std::string x("hello, world");

int main () { Foo(x); x.test(); }

print "test"


What you want is use uniform initialization syntax Foo{x}

struct Foo {
    Foo (std::string x) { std::cout << x << std::endl; }
};

std::string x("hello, world");

int main () { Foo{x}; }

print "hello, world"

Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
8

Foo(x); means the same as Foo x; . You can add redundant parentheses to the name of the variable.

So you need the default constructor because this is creating a variable x with no arguments being passed to constructor.

You can workaround this by doing Foo{x}; in C++11.

The parsing rule is that if something could be a valid declaration and a valid non-declaration statement, then it is in fact a declaration. See also most vexing parse

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
  • "workaround"? No no no! It's the solution! It should be done for everything! Brace initialization is great! :-) – Mark Garcia Jul 08 '14 at 01:51
  • @MarkGarcia it seems to have its ups and downs... eg. `vector x{{"a", "b", "c"}};` is OK, but `vector x{{"a", "b"}};` causes undefined behaviour! – M.M Jul 08 '14 at 01:54
  • @Deduplicator, Not that I know of with the semicolon there. – chris Jul 08 '14 at 01:54
  • 2
    @MattMcNabb, And using single braces works for both :) I think brace-initialization is great when you know what to look out for. – chris Jul 08 '14 at 01:55
  • @chris: Please elaborate. What's wrong with a simple cast? – Deduplicator Jul 08 '14 at 01:56
  • @Deduplicator, As far as I know, `Type(identifier);` is always a declaration. `Type(identifier)` without the semicolon is a functional-style cast. Unfortunately, the plot thickens when `identifier` is replaced with `expression`. If you have a previous `x`, `Type(x);` is still a declaration. `Type(2);` is not. Even having a global `x` and doing `Type(::x);` fails to compile. – chris Jul 08 '14 at 01:57
  • 1
    What exactly is the problem with `Type(::x);` ? – M.M Jul 08 '14 at 02:05
  • 1
    @MattMcNabb, No clue. – chris Jul 08 '14 at 02:15
  • 1
    @MattMcNabb, It turns out `Type(::x);` compiles with GCC 4.9. I [asked a new question](http://stackoverflow.com/questions/24623071/is-typex-valid). – chris Jul 08 '14 at 03:08
-1

I completely agree with above solution. Though this will still work:

struct Foo {
    Foo (string x) 
    { 
        cout << x << endl; 
    }
};


int main () 
{ 
    string x = "hello, world";
    Foo * abc = new Foo(x); 
    return 0;
}
Abhishek Mittal
  • 356
  • 1
  • 16