1

In Essentials of Modern C++ Style (video), Herb Sutter advocates:

auto varname = Constructor{ ... };

instead of

Constructor varname( ... );

I tried doing:

auto log = fstream{"log.txt", fstream::out};

but received an error message from g++4.8 -std=c++11 about deleted functions (regardless of whether I use curly brackets or parentheses).

Is it my fault or g++'s?

fstream log{"log.txt", fstream::out};

works fine.

MCVE:

#include <fstream>

using namespace std;
int main(int argc, char **argv)
{
    auto log = fstream{"log.txt", fstream::out};
    //fstream log{"log.txt", fstream::out};
    log << "hello world" << endl;
}

Error:

g++ -std=c++11    1.cc   -o 1
1.cc: In function ‘int main(int, char**)’:
1.cc:6:47: error: use of deleted function ‘std::basic_fstream<char>::basic_fstream(const std::basic_fstream<char>&)’
     auto log = fstream{"log.txt", fstream::out};
                                               ^
In file included from 1.cc:1:0:
/usr/include/c++/4.8/fstream:776:11: note: ‘std::basic_fstream<char>::basic_fstream(const std::basic_fstream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
     class basic_fstream : public basic_iostream<_CharT, _Traits>
           ^
/usr/include/c++/4.8/fstream:776:11: error: use of deleted function ‘std::basic_iostream<char>::basic_iostream(const std::basic_iostream<char>&)’
In file included from /usr/include/c++/4.8/fstream:38:0,
                 from 1.cc:1:
/usr/include/c++/4.8/istream:795:11: note: ‘std::basic_iostream<char>::basic_iostream(const std::basic_iostream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
     class basic_iostream
           ^
/usr/include/c++/4.8/istream:795:11: error: use of deleted function ‘std::basic_istream<char>::basic_istream(const std::basic_istream<char>&)’
/usr/include/c++/4.8/istream:58:11: note: ‘std::basic_istream<char>::basic_istream(const std::basic_istream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
     class basic_istream : virtual public basic_ios<_CharT, _Traits>
           ^
/usr/include/c++/4.8/istream:58:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
In file included from /usr/include/c++/4.8/ios:44:0,
                 from /usr/include/c++/4.8/istream:38,
                 from /usr/include/c++/4.8/fstream:38,
                 from 1.cc:1:
/usr/include/c++/4.8/bits/basic_ios.h:66:11: note: ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’ is implicitly deleted because the default definition would be ill-formed:
     class basic_ios : public ios_base
           ^
In file included from /usr/include/c++/4.8/ios:42:0,
                 from /usr/include/c++/4.8/istream:38,
                 from /usr/include/c++/4.8/fstream:38,
                 from 1.cc:1:
/usr/include/c++/4.8/bits/ios_base.h:786:5: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
     ios_base(const ios_base&);
     ^
In file included from /usr/include/c++/4.8/ios:44:0,
                 from /usr/include/c++/4.8/istream:38,
                 from /usr/include/c++/4.8/fstream:38,
                 from 1.cc:1:
/usr/include/c++/4.8/bits/basic_ios.h:66:11: error: within this context
     class basic_ios : public ios_base
           ^
In file included from /usr/include/c++/4.8/fstream:38:0,
                 from 1.cc:1:
/usr/include/c++/4.8/istream:795:11: error: use of deleted function ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’
     class basic_iostream
           ^
In file included from /usr/include/c++/4.8/istream:39:0,
                 from /usr/include/c++/4.8/fstream:38,
                 from 1.cc:1:
/usr/include/c++/4.8/ostream:58:11: note: ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
     class basic_ostream : virtual public basic_ios<_CharT, _Traits>
           ^
/usr/include/c++/4.8/ostream:58:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
In file included from /usr/include/c++/4.8/fstream:38:0,
                 from 1.cc:1:
/usr/include/c++/4.8/istream:795:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
     class basic_iostream
           ^
In file included from 1.cc:1:0:
/usr/include/c++/4.8/fstream:776:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
     class basic_fstream : public basic_iostream<_CharT, _Traits>
           ^
/usr/include/c++/4.8/fstream:776:11: error: use of deleted function ‘std::basic_filebuf<char>::basic_filebuf(const std::basic_filebuf<char>&)’
/usr/include/c++/4.8/fstream:72:11: note: ‘std::basic_filebuf<char>::basic_filebuf(const std::basic_filebuf<char>&)’ is implicitly deleted because the default definition would be ill-formed:
     class basic_filebuf : public basic_streambuf<_CharT, _Traits>
           ^
In file included from /usr/include/c++/4.8/ios:43:0,
                 from /usr/include/c++/4.8/istream:38,
                 from /usr/include/c++/4.8/fstream:38,
                 from 1.cc:1:
/usr/include/c++/4.8/streambuf:802:7: error: ‘std::basic_streambuf<_CharT, _Traits>::basic_streambuf(const std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’ is private
       basic_streambuf(const basic_streambuf& __sb)
       ^
In file included from 1.cc:1:0:
/usr/include/c++/4.8/fstream:72:11: error: within this context
     class basic_filebuf : public basic_streambuf<_CharT, _Traits>
           ^
make: *** [1] Error 1
Community
  • 1
  • 1
Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • Please post the error message. – MokaT Jul 10 '15 at 12:06
  • 1
    Please provide a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) and the full error message. – Shafik Yaghmour Jul 10 '15 at 12:09
  • 1
    Probably you are referring to Herb Sutter's advice. However, fstream's copy constructor is `delete`, so that might be the problem. – Ilio Catallo Jul 10 '15 at 12:11
  • Note if you are going to use a C++ version specific tag like C++11 you should also include the main tag C++ in this case. – Shafik Yaghmour Jul 10 '15 at 12:25
  • By the way, the constants such as `out` are actually declared in `ios`, so you can reference them as `ios::out` instead of `fstream::out`... though it probably doesn't really matter. – celticminstrel Jul 10 '15 at 14:47

2 Answers2

5

The auto var = Type{...}; syntax requires Type to be move-constructible, but gcc did not implement movable fstreams until GCC 5.1. Your code compiles with GCC 5.1.

cpplearner
  • 13,776
  • 2
  • 47
  • 72
1

If I'm not wrong that advice comes from Herb Sutter.

Apparently, the problem is due to the fact that you cannot copy-construct std::fstream (std::fstream's copy constructor is marked as delete). However, intuitively one would say that, since you have a temporary on the right-hand side, the move-constructor rather than the copy-constructor should be used.

In fact, the following compiles fine on clang (clang++ -std=c++11, OS X Mavericks):

#include <iostream>
#include <fstream>

int main() {

auto log = std::fstream{"test.cpp", std::fstream::out};

}
Ilio Catallo
  • 3,152
  • 2
  • 22
  • 40
  • 3
    Regarding your first sentence: Yes, indeed, and he coined the term "AAA" (Almost Always Auto) for it. See http://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/. However, to my knowledge, this style has not been widely adopted yet. Personally, I'm unsure about its advantages and disadvantages. – Christian Hackl Jul 10 '15 at 12:28