Am I better off learning with GCC rather than VC++?

Pages: 12
I tried Geany and CodeBlocks and found it took too long to debug with those, and went with VS C++, and was much more productive right off the bat.

However, I'm testing out CLion, and using it to compile some of my VC++ code, which compiled ok in VC++, and I'm running into errors when compiling with GCC as the compiler for CLion.

Had something to do with ofstream needed to be a reference, not by value. Compiled ok in VC++, blew up in GCC, with really not a very helpful error message.

So, if I wanted to make sure I learn the best, should I be letting GCC dictate how I code?

Not trying to start an opinion war, just trying to gauge what route to take. The more permissive (I assume) VC++ is hard enough already without making things harder, but I'm looking at the long term.
> Am I better off learning with GCC rather than VC++?

No, if you are on Windows, use Visual Studio as the primary development environment.

Using two different compilers to compile the code is a good idea; one may point out problems in your code that the other fails to catch.

With Visual Studio adding clang++ as a second compiler is quite straightforward:
https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.llvm-toolchain#overview
> The more permissive (I assume) VC++ is hard enough already without making things harder
Therein lies the trap.
Permissiveness is the opposite of correctness.

You need to learn C++ (the language), not what any particular implementation (VC++, GCC, Clang) will let you get away with. In your programming life, you'll use many compilers, so you can't afford to learn a bunch of "VC++ does this, GCC does that" rules.

JLBorges suggestion of running multiple compilers is a good one. It might not seem like it at the moment, but getting something to compile and work on one compiler is quite easy.

But if you can compile the same code with two compilers, and get the same run-time results, you can be fairly confident that you're doing it right.

> Compiled ok in VC++, blew up in GCC, with really not a very helpful error message.
Barring obscure compiler bugs, you would believe GCC in this instance. Always go with the most pessimistic assessment of your code.

Had you not tried GCC, you would have carried on with your mistaken "ofstream by value" idea. It might work for now, but at some point it would stop working. But by then, the "bug" would also in your mind (as well as in your code), and mistaken ideas can be hard to shift.
Thanks to you both. Yeah, the GCC message was a bit cryptic for me to decipher.

error: use of deleted function 'std::basic_ofstream<_CharT, _Traits>::basic_ofstream(const std::basic_ofstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]'
write_header(ofsTblLtdFile);


Couldn't find anything that could explain that to me. Finally the folks at CLion gave me some pointers.
You would get this error if you are using a somewhat old version of GCC and try to pass file streams as rvalues. They were somewhat late in implementing move semantics for file based streams.
error: use of deleted function 'Foo::Foo(const Foo&)'

I can create that error too:
1
2
3
4
5
6
7
8
9
10
11
12
struct Foo {
    Foo() = default;
    Foo( const Foo & ) = delete; // disallow copy construction
};

void bar( Foo ) {}

int main()
{
    Foo snafu;
    bar ( snafu );
}

 In function 'int main()':
11:17: error: use of deleted function 'Foo::Foo(const Foo&)'
3:5: note: declared here
6:6: error: initializing argument 1 of 'void bar(Foo)'

The difference between Foo and basic_ofstream is that the latter is a template and is in namespace std.

Furthermore, your code did not have verbatim basic_ofstream, did it?
You had ofstream that is an alias for basic_ofstream<char, std::char_traits<char>>


Standard Library uses templates etc and that tends to make the error messages verbose. Some compilers might use more humane language than others, but the one that says nothing is not the one you want to use.

IDE is not compiler. IDE uses a compiler. IDE might help on formatting the error messages.


No compiler has 100% support for the entire C++ Standard.
Most have extensions that allow nonstandard constructs. Those are not portable.
My definition code is:

1
2
bool write_header(std::ofstream );
bool write_detail(std::ofstream , address_struct &);


adding &, as the folks at CLion suggested, did not help.

You are using a fairly old version of GCC. One which hadn't yet implemented move semantics for file streams.

> adding &, as the folks at CLion suggested, did not help.

It would help if the stream is a lvalue.

This is an error:
1
2
3
4
5
6
bool write_header( std::ofstream& );

int main()
{
    write_header( std::ofstream( "myfile.txt" ) ) ; 
}


This would be fine:
1
2
3
4
5
6
7
bool write_header( std::ofstream& );

int main()
{
    std::ofstream my_file( "myfile.txt" ) ;
    write_header(my_file) ; 
}
My definition code is:

bool write_header(std::ofstream );
bool write_detail(std::ofstream , address_struct &);

adding &, as the folks at CLion suggested, did not help.


Surely that should be:
1
2
bool write_header(std::ofstream & );
bool write_detail(std::ofstream &, address_struct &);


If you don't pass by reference but only by value, then how would the calling procedure know if the stream was in a failed state after visiting those functions?

Neither gcc or VC++ compiler on rextester.com will allow it unless it is passed by reference.

Perhaps you should show more complete code.
Last edited on
> how would the calling procedure know if the stream was in a failed state after visiting those functions?

Like this, with a conforming implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <fstream>

bool write_header( std::ofstream file )
{
    return bool( file << "text of header\n" ) ;
}

int main ()
{
    if( write_header( std::ofstream( "my_file.txt" ) ) )
        std::cout << "write header: success!\n" ;
}
Like this, with a conforming implementation:


??? I don't understand what you are trying to say. It was passed by value ... and it duly failed to compile.
With C++11 or later, file streams are move constructible.
Snippet: http://coliru.stacked-crooked.com/a/b1072a5f1830fc9b

Sorry, still don't get it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <fstream>

bool write_header( std::ofstream file )
{
    // Some operation that puts file in a failed state
    // Other stuff
    return true;       // because this was looking at something other than file
}

int main ()
{
    std::ofstream out( "my_file.txt" );
    write_header( out );
    out << "Is this legitimate or not?";
}
GCC and G++ have dates of 5/18/2018, and I just downloaded

i686-8.1.0-posix-dwarf-rt_v6-rev0 yesterday, and this is where CLion is autodetecting the compiler.

> Is this legitimate or not?

Because out is an lvalue, and the copy constructor is deleted, it won't compile.

This is fine:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <fstream>

bool write_header( std::ofstream file )
{
    // file output operations
    
    return bool(file); // return true if the stream is not in a failed state
}

int main ()
{
    std::ofstream out( "my_file.txt" );
    if( write_header( std::move(out) ) )
    {
        // successfully wrote stuff into the file
    }
}
@lastchance

It compiled in VC++ when by value, but not with G++/CLion.

Ok, more complete code:


1
2
3
4
5
6
7
8
9
10
11
12
13
bool write_header(std::ofstream );

bool write_detail(std::ofstream , address_struct &);

bool write_header(ofstream ofs) {

		ofs << "CODEX" << '\t'; 
                ofs << '\n';
}

bool write_detail(std::ofstream  ofs, address_struct &  address) {
		ofs << address.codex_num << '\t'  ;
}


Last edited on
zydeholic: What's the actual code?
zydeholic wrote:
It compiled in VC++ when by value, but not with G++/CLion.
JLBorges wrote:
Because out is an lvalue, and the copy constructor is deleted, it won't compile.


Are we talking about the same code?
Ok, more complete code:

Well, neither of your functions seems to return anything ... but they promised (anthropomorphic as ever!) to return a bool.

It's a personal thing, but I would make them both void functions and pass ofstreams (or, possibly, ostreams) by reference.
Last edited on
closed account (E0p9LyTq)
Am I better off learning with GCC rather than VC++?

Learn to use both, one might catch problems with your code the other misses.

Plus, make sure each is as up-to-date as possible. Unless you are maintaining code that needs an older C++ standard using outdated tools can lead to problems.

I use VS17 and Code::Block 17.12 for most of my coding. I am little bit by little bit learning how to do coding by command line and hand crafted make files. It is a bit frustrating at times, but I keep working at improving my skills.

Unless GCC has finally fixed things <random>'s implementation of std::random_device is not truly random. std::random_device::entropy returns zero, indicating GCC is using a pseudo-random number engine.
Pages: 12