Here is data serialization program which compiles with gcc 11.1:
#include <fstream>
#include <ranges>
#include <concepts>
#include <map>
using namespace std;
void write( fstream & f, const integral auto & data ) {
f.write( (const char*)&data, sizeof( data ) );
}
void write( fstream & f, const pair<auto,auto> & p ) {
write( f, p.first );
write( f, p.second );
}
template< ranges::range T >
void write( fstream & f, const T & data ) {
const uint64_t size = ranges::size( data );
write( f, size );
for ( const auto & i : data )
write( f, i );
}
int main() {
auto f = fstream( "spagetti", ios::out | ios::binary );
const bool pls_compile = true;
if constexpr (pls_compile) {
write( f, pair< int, int >( 123, 777 ) );
write( f, map< int, int >{ { 1, 99 }, { 2, 98 } } );
}
else
write( f, pair< map< int, int >, int >( { { 1, 99 }, { 2, 98 } }, 777 ) );
}
which made me a happy developer of serialization library which provides functions to serialize to file anything that is integral || pair || range. But it turned out that if you set pls_compile = false, then compilation fails with spagetti.cpp:12:10: error: no matching function for call to 'write(std::fstream&, const std::map<int, int>&)'. It can't be fixed by moving declaration of write( pair ) past write( range ) because pls_compile = true will stop compiling then.
What is the best way to fix it and why compiler forgets about existence of write( range ) while generating implementation of write( pair< map, int > ) based on write( pair ) template? It clearly should be already familiar with write( range ) since it already proceeded down to write( pair< map, int > ).