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

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

user11578
1#
user11578 Published in September 19, 2018, 3:57 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 { ... };

template<>
struct visitable_tag<Foo> {};
}

 // or maybe have tag in special namespace
 namespace visitable_tag_namespace {
 template<>
 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.

share|improve this question
  • 6
    Define your operator<< template in the same namespace as that of the types generated by your middleware compiler. – Praetorian Jan 10 at 19:52
  • 2
    @Praetorian That would make a nice answer – Passer By Jan 10 at 19:54
  • 1
    Another option is an empty interface/base class, used only for "tagging". The compiler will apply empty base optimization so the extra base class has no runtime effect. And then you can use SFINAE to activate operator<< only for classes derived from the tag type. – Ben Voigt Jan 10 at 19:55
  • @Praetorian unfortunately those types are generated in different namespaces – Slava Jan 10 at 19:59
  • @PasserBy I was pretty much certain a restriction like the comment above would pop up for that answer :) Slava, you claim you can modify the compiler, so maybe you can get it to generate these types in one, or just a handful of namespaces. – Praetorian Jan 10 at 20:01

3 Answers 3

active oldest votes
up vote 0 down vote
You need to login account before you can post.

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

© 2016 Powered by mzan.com design MATCHINFO