2

Can't compile this small code on Linux:

#include <fstream>
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
    char fileName[512];
    sprintf(fileName, "test");
    ofstream iriFile(string(fileName));
    iriFile<<",";
    return 0;
}

I am compiling like this: g++ test.cpp and am getting this:

test.cpp:12:11: error: invalid operands of types ‘std::ofstream(std::__cxx11::string) {aka std::basic_ofstream(std::__cxx11::basic_string)}’ and ‘const char [2]’ to binary ‘operator<<’ iriFile<<",";

What might be the reason?

Stepan Yakovenko
  • 8,670
  • 28
  • 113
  • 206
  • 6
    `ofstream iriFile(string(fileName));` is a function declaration, see Most Vexing Parse. No time to look for the best dupe now, but in general, the compiler can warn you about that. https://wandbox.org/permlink/tgimOpyhXGcD1Spu – Baum mit Augen Jan 09 '18 at 16:04
  • 3
    Very related: https://stackoverflow.com/questions/7007817/a-confusing-detail-about-the-most-vexing-parse – Rakete1111 Jan 09 '18 at 16:04
  • That's a lot of wheel-spinning; just say `ofstream iriFile("test");` – Pete Becker Jan 09 '18 at 16:33
  • There are quite a few posts in SO on the topic of the most vexing parse. See https://stackoverflow.com/search?q=%5Bcpp%5D+most+vexing+parse. The crux of the problem is that `ofstream iriFile(string(fileName));` is parsed as `ofstream iriFile(string fileName);`, which is just a function declaration. – R Sahu Jan 09 '18 at 16:36
  • It's often worth testing with both GCC and Clang if you can't figure an error out: *warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]* – chris Jan 09 '18 at 16:39
  • Change `ofstream iriFile(string(fileName));` to `ofstream iriFile{string(fileName)};`, to avoid the Most Vexing Parse. – Eljay Jan 09 '18 at 17:52

3 Answers3

1

Ok, the solution is to remove implicit string() creation:

string sFileName(fileName)
ofstream iriFile(sFileName);
Stepan Yakovenko
  • 8,670
  • 28
  • 113
  • 206
1

First of all you do not need to explicitly convert const char * to std::string there is std::ifstream constructor for it:

 std::ofstream iriFile(fileName);

but if you want to be extra safe and verbose use proper C++ then:

std::ofstream iriFile( static_cast<std::string>(fileName) );

not C style cast.

Slava
  • 43,454
  • 1
  • 47
  • 90
0

As you pointed out, removing the explicit string creation fixes it.

It could be worth to add that this can also be fixed for types with explicit constructors by using list initialization, like so:

ofstream iriFile(string{sFileName});
amc176
  • 1,514
  • 8
  • 19
  • It's because im not a native english speaker and words like `explicit` and `implicit` confuse me a little. So I just copied the word because I thought thats what I wanted to say. I'll correct it. – amc176 Jan 09 '18 at 16:21