I am implementing serialization that's supposed to work by recursive overloading until serializing data breaks down to primitive types. Here it's relevant code at serialization.hpp
:
#pragma once
#include <fstream>
#include <ranges>
#include <concepts>
using namespace std;
void write( fstream & f, const integral auto & data );
void write( fstream & f, const pair<auto,auto> & p );
void write( fstream & f, const ranges::range auto & data );
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 );
}
void write( fstream & f, const ranges::range auto & data ) {
const uint64_t size = ranges::size( data );
write( f, size );
for ( const auto & i : data ) {
write( f, i );
}
}
And it works well for most types providing serialization for free even for std::map
, std::list
, etc. If user needs to serialize any custom type then it's needed to just provide a void write( fstream & f, const CustomType & t ) { ... }
function and it supposed to get serialized even inside any data structure. And it works well until CustomData
gets wrapped into a namespace. main.cpp
:
#include "serialization.hpp"
#include <fstream>
#include <map>
using namespace std;
struct MyData {
int custom_data[ 666 ];
};
void write( fstream & f, const MyData & d ) {
write( f, d.custom_data[ 123 ] );
}
namespace my_namespace {
struct NamespacedData {
int custom_data[ 777 ];
};
}//namespace my_namespace
void write( fstream & f, const my_namespace::NamespacedData & d ) {
write( f, d.custom_data[ 7 ] );
}
int main() {
auto f = fstream( "my_data.binary", ios::out | ios::binary );
f.exceptions( fstream::badbit | fstream::failbit | fstream::eofbit );
map< int, MyData > my_map;
//DOES work:
write( f, my_map );
map< int, my_namespace::NamespacedData > namespaced_map;
//does NOT work:
write( f, namespaced_map );
}
Compilation fails with error: serialization.hpp:16:10: error: no matching function for call to ‘write(std::fstream&, const my_namespace::NamespacedData&)’ ...
How function argument's full name matters here? Isn't it's irrelevant when compiler should try to match any type when looking for fitting overloaded function? Or it's just gcc
bug?
Command: g++ main.cpp -std=gnu++20 -fconcepts
g++ version 11.3.0