3

When creating a temporary object in a scope, the compiler doesn't see the provided argument to the constructor and gives a compiling error.

As in the following example:

#include <sstream>
#include <iostream>

class csventry
{
public:
        csventry(std::ostream& ostream) :
                _ostream(ostream)
                {}

        ~csventry() 
                { _ostream << std::endl; }

        csventry& operator << (const std::string& value) {
                _ostream << ", ";
                _ostream << value;
                return *this;
        }

private:
        std::ostream& _ostream;
};

int main () 
{
        std::ostringstream log;

        { csventry(log) << "User Log-on:"; }
        { csventry(log); }
        { csventry(log) << "Summary:"; }

        std::cout<<log.str()<<std::endl;
}

I get this error.

main.cpp: In function ‘int main()’:
main.cpp:29:16: error: no matching function for call to ‘csventry::csventry()’
  { csventry(log); }
                ^
main.cpp:7:2: note: candidate: csventry::csventry(std::ostream&)
  csventry(std::ostream& ostream) :
  ^~~~~~~~
main.cpp:7:2: note:   candidate expects 1 argument, 0 provided
main.cpp:4:7: note: candidate: constexpr csventry::csventry(const csventry&)
 class csventry
       ^~~~~~~~
main.cpp:4:7: note:   candidate expects 1 argument, 0 provided

Tried with gcc 7.3 and 5.4

It worked when I name the temporary object, { csventry entry(log); }

Why does the compiler miss the provided argument?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Tr03P
  • 41
  • 2
  • I'm uncertain about what happens but I have a little work-around: [Live Demo on coliru](http://coliru.stacked-crooked.com/a/957b107eea29ffa2). (I introduced a helper function.) – Scheff's Cat Aug 16 '18 at 14:37
  • 1
    related/dupe: https://stackoverflow.com/questions/29675601/why-does-c-allow-us-to-surround-the-variable-name-in-parentheses-when-declarin – NathanOliver Aug 16 '18 at 14:43
  • Btw why do you need to put temporaries into scope? If you would not you would catch the reason of the error sooner. – Slava Aug 16 '18 at 14:47

1 Answers1

10

csventry(log); doesn't create a temporary object as you expected; parentheses are considered redundant, in fact it declares an object named log with type csventry, i.e. it's same as csventry log;. As the error message said, it fails because csventry doesn't have the default constructor.

As the workaround you can change it to csventry{log};.

[stmt.ambig]/1:

(emphasis mine)

There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405