Home C++ Generic way to provide `operator<<` for middleware generated types
Reply: 0

C++ Generic way to provide `operator<<` for middleware generated types

user2678 Published in June 24, 2018, 3:25 am

We use a middleware that generates types for us for various programming languages, including C++. For structures generated for C++ I want to inject code that can be used for various data conversion, for example output to std::ostream. Let's say we have following structure generated:

struct Foo {
    int a;
    double d;

Let's say I change middleware compiler to produce following template function:

template<typename Visitor>
void visit( Visitor &v, const Foo &data )
    v.visit( "a", data.a );
    v.visit( "d", data.d );

now I can use this code for various ways and it should not affect anything if not used, for example make std::ostream::operator<<:

struct OstreamVisitor {
    OstreamVisitor( std::ostream &os ) : m_os( os ) {}

    void visit( const char *name, int i ) { m_os << name << "=" << i << std::endl; }
    void visit( const char *name, double d ) { m_os << name << "=" << d << std::endl; }

    std::ostream &m_os;

std::ostream &operator<<( std::ostream &out, const Foo &data )
    OstreamVisitor v( out );
    visit( v, data );
    return out;

it works live example but problem is I do not want to write std::ostream &operator<< for every structure manually so naive solution would be to write:

template<typename T>
std::ostream &operator<<( std::ostream &os, const T &t );

and use visitor, but that would interfere with other types, that not generated. So is there way to make such generic function that limited only for structures, that generated? I would like not to inject anything to generated structures if possible but having template class instead of template function is fine.

Note: I cannot restrict generated structs to belong to particular namespace unfortunately. What I am thinking is something like:

// system header
template<typename T>
struct visitable_tag;

// generated header
namespace FooNamespace {
struct Foo { ... };

struct visitable_tag<Foo> {};

 // or maybe have tag in special namespace
 namespace visitable_tag_namespace {
 struct visitable_tag<FooNamespace::Foo> {};

and then make template output function only instantiate when such specialization exits. Of course this is just idea of possible tagging and I open to other ways, but would prefer to have original structures untouched.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.309857 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO