I'm writing a function in C++ that has to return more than one value, and I know that I can't. So I thought to pass the function two pointers to the files I want to open. This is the code and then I'll explain my problem:
void openSourceOutputFiles(string sourceFilename, string outputFilename,
fstream *source, fstream *output){
fstream sourceFile(sourceFilename);
fstream outputFile(outputFilename);
*source = sourceFile;
*output = outputFile;
}
I'm compiling with G++, and it says that I can't assign to the fstream* pointer an fstream. I tried also to modify it as this:
void openSourceOutputFiles(string sourceFilename, string outputFilename,
fstream *source, fstream *output){
fstream sourceFile(sourceFilename);
fstream outputFile(outputFilename);
*source = &sourceFile;
*output = &outputFile;
}
but it didn't work. This is instead the full code I'm working on:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
string sourceFilename, outputFilename;
string sourceContent, outputContent;
fstream *source, *output;
void getSourceOutputFiles(string *source, string *output) {
cout << "Source ";
cin >> *source;
cout << "Output ";
cin >> *output;
}
void openSourceOutputFiles(string sourceFilename, string outputFilename,
fstream *source, fstream *output){
fstream sourceFile(sourceFilename);
fstream outputFile(outputFilename);
*source = &sourceFile;
*output = &outputFile;
}
int main() {
getSourceOutputFiles(&sourceFilename, &outputFilename);
openSourceOutputFiles(sourceFilename, outputFilename, *source, *output);
return 0;
}
G++ error:
main.cpp: In function 'void openSourceOutputFiles(std::string, std::string, std::fstream*, std::
fstream*)':
main.cpp:22:15: error: no match for 'operator=' (operand types are 'std::fstream' {aka 'std::bas
ic_fstream<char>'} and 'std::fstream*' {aka 'std::basic_fstream<char>*'})
22 | *source = source;
| ^~~~~~
In file included from main.cpp:3:
C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/fstream:1186:7: note: can
didate: 'std::basic_fstream<_CharT, _Traits>& std::basic_fstream<_CharT, _Traits>::operator=(std
::basic_fstream<_CharT, _Traits>&&) [with _CharT = char; _Traits = std::char_traits<char>]'
1186 | operator=(basic_fstream&& __rhs)
| ^~~~~~~~
C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/fstream:1186:33: note:
no known conversion for argument 1 from 'std::fstream*' {aka 'std::basic_fstream<char>*'} to 'st
d::basic_fstream<char>&&'
1186 | operator=(basic_fstream&& __rhs)
| ~~~~~~~~~~~~~~~~^~~~~
main.cpp:23:15: error: no match for 'operator=' (operand types are 'std::fstream' {aka 'std::bas
ic_fstream<char>'} and 'std::fstream*' {aka 'std::basic_fstream<char>*'})
23 | *output = output;
| ^~~~~~
C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/fstream:1186:7: note: can
didate: 'std::basic_fstream<_CharT, _Traits>& std::basic_fstream<_CharT, _Traits>::operator=(std
::basic_fstream<_CharT, _Traits>&&) [with _CharT = char; _Traits = std::char_traits<char>]'
1186 | operator=(basic_fstream&& __rhs)
| ^~~~~~~~
C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/fstream:1186:33: note:
no known conversion for argument 1 from 'std::fstream*' {aka 'std::basic_fstream<char>*'} to 'st
d::basic_fstream<char>&&'
1186 | operator=(basic_fstream&& __rhs)
| ~~~~~~~~~~~~~~~~^~~~~
PS C:\Users\Allenips Development\Documents\C-C++\Varm> g++ main.cpp -o main.exe
main.cpp: In function 'void openSourceOutputFiles(std::string, std::string, std::fstream*, std::
fstream*)':
main.cpp:22:15: error: no match for 'operator=' (operand types are 'std::fstream' {aka 'std::bas
ic_fstream<char>'} and 'std::fstream*' {aka 'std::basic_fstream<char>*'})
22 | *source = source;
| ^~~~~~
In file included from main.cpp:3:
C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/fstream:1186:7: note: can
didate: 'std::basic_fstream<_CharT, _Traits>& std::basic_fstream<_CharT, _Traits>::operator=(std
::basic_fstream<_CharT, _Traits>&&) [with _CharT = char; _Traits = std::char_traits<char>]'
1186 | operator=(basic_fstream&& __rhs)
| ^~~~~~~~
C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/fstream:1186:33: note:
no known conversion for argument 1 from 'std::fstream*' {aka 'std::basic_fstream<char>*'} to 'st
d::basic_fstream<char>&&'
1186 | operator=(basic_fstream&& __rhs)
| ~~~~~~~~~~~~~~~~^~~~~
main.cpp:23:15: error: no match for 'operator=' (operand types are 'std::fstream' {aka 'std::bas
ic_fstream<char>'} and 'std::fstream*' {aka 'std::basic_fstream<char>*'})
23 | *output = output;
| ^~~~~~
C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/fstream:1186:7: note: can
didate: 'std::basic_fstream<_CharT, _Traits>& std::basic_fstream<_CharT, _Traits>::operator=(std
::basic_fstream<_CharT, _Traits>&&) [with _CharT = char; _Traits = std::char_traits<char>]'
1186 | operator=(basic_fstream&& __rhs)
| ^~~~~~~~
C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/fstream:1186:33: note:
no known conversion for argument 1 from 'std::fstream*' {aka 'std::basic_fstream<char>*'} to 'st
d::basic_fstream<char>&&'
1186 | operator=(basic_fstream&& __rhs)
| ~~~~~~~~~~~~~~~~^~~~~
I don't figure out how to solve this issue. What am I missing? If I explained myself badly, please tell me in the comments and I'll edit the question.
Even if you fix the syntax issue mentions in a comment below this answer (*
is incorrect), it doesn't "work" because you are trying to return pointers to local variables whose lifetimes end when the function returns. You are then using dangling references in the caller.
I'm writing a function in C++ that has to return more than one value, and I know that I can't.
You absolutely can:
auto openSourceOutputFiles(std::string sourceFilename, std::string outputFilename){
std::fstream sourceFile(sourceFilename);
std::fstream outputFile(outputFilename);
return std::make_tuple(std::move(sourceFile), std::move(outputFile));
}
//caller:
auto [sourceFile, outputFile] = openSourceOutputFiles(/*...*/);
However, if this is not a one-of use, it is a better idea to use a structure with names instead of a tuple, so that the caller can identify what each item represents:
auto openSourceOutputFiles(string sourceFilename, string outputFilename){
struct Result {
std::fstream sourceFile;
std::fstream outputFile;
};
std::fstream sourceFile(sourceFilename);
std::fstream outputFile(outputFilename);
return Result{std::move(sourceFile), std::move(outputFile)};
}
Caller site can remain unchanged, but can also do
auto files = openSourceOutputFiles(/*...*/);
and then access files.sourceFile
and files.outputFile
.