I'm facing with an issue. Returning std::pair<T1, T2> from lambda function. I'm trying to generate map with opened ifstream's, but compiler complains with this output:
/usr/include/c++/9/bits/stl_algo.h:4337:12: error: use of deleted function ‘std::pair<const std::__cxx11::basic_string, std::basic_ifstream >& std::pair<const std::__cxx11::basic_string, std::basic_ifstream >::operator=(const std::pair<const std::__cxx11::basic_string, std::basic_ifstream >&)’
I went through cppref for std::pair and I didn't notice that copy operator= is not viable for this one.
I'm fairly certain that lambdas that return pair is possible, then I definitely have some misunderstanding in snippet below.
std::map<int, std::string> mFileMap;
std::map<std::string, std::ifstream> files;
std::transform(mFileMap.begin(), mFileMap.end(), files.begin(),
[](const auto& arg) -> std::pair<std::string, std::ifstream> {
std::string path(arg.second);
std::ifstream stream(path);
return std::make_pair(path, stream);
});
std::pair
is copyable only as long as whatever's in a std::pair
is copyable. If you think about, for a few seconds, you will agree that this makes 100% sense.
std::pair<std::string, std::ifstream>
std::ifstream
is not copyable. You cannot copy std::ifstream
s. Putting it inside a std::pair
doesn't make it copyable.
But that's not the least of the problems in the shown code:
std::map<std::string, std::ifstream> files;
std::transform(mFileMap.begin(), mFileMap.end(), files.begin(),
// ...
The files
map is empty. files.begin()
will return the beginning iterator to an empty map, which will be the same value as files.end()
. Attempting to copy into an ending iterator (ignoring the fact that the underlying type is not copyable) will not end well.
Additionally, std::map
's key is constant, in the map, so that won't work either.
This is not how stuff gets added to a map, one needs to use a std::insert_iterator
.
So, to summarize, the following problems must be solved:
std::pair
is not copyable.std::insert_iterator
must be used to insert new key/value pairs into a std::map
.Presuming you insist on your std::map
containing these values, you'll have to do some work to populate it, using std::map::emplace
, this will be the most practical way to drop new things into this map.
thanks to Sam I found the way to solve this problem. So, one possible fix could be
std::map<std::string, std::ifstream> files;
std::transform(mFileMap.begin(), mFileMap.end(), std::inserter(files, files.end()),
[](auto const& arg) -> std::pair<std::string, std::ifstream> {
std::string path(arg.second);
return std::make_pair(path, std::ifstream(path));
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With