You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@thrift.apache.org by "James E. King, III (JIRA)" <ji...@apache.org> on 2017/02/09 15:37:41 UTC

[jira] [Updated] (THRIFT-4060) Thrift printTo ostream overload mechanism breaks down when types are nested

     [ https://issues.apache.org/jira/browse/THRIFT-4060?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

James E. King, III updated THRIFT-4060:
---------------------------------------
    Description: 
I'm in the middle of converting a project that provides some ostream operators (for logging purposes) for a number of thrift structures.  The project was using 0.8.0 and in 0.9.3 some ostream operator overloads were added with THRIFT-3336.  The solution that was provided here runs into complications if a thrift structure is contained within another one.  Take this simple example:

h4. Thrift
{noformat}
namespace cpp example.detail

struct Lower {
   1: binary lowerBinary
}

struct Higher {
    1: set<Lower> lowers
}
{noformat}

h4. C++
{noformat}
namespace example {

class MyLower : public detail::Lower
{
    virtual void printTo(std::ostream& os) const override;
}

class MyHigher : public detail::Higher
{
    virtual void printTo(std::ostream& os) const override
    {
        os << lowers;
        // here's the problem, lowers is a set<detail::Lower> when it serializes in,
        // not a set<MyLower>, so I cannot override it...
    }
}

}
{noformat}

I'm considering adding an annotation to the thrift IDL that the compiler will recognize that allows someone to say, "I am going to provide my own operator<< for this structure, don't generate one".  This would replace the printTo mechanism that was added in THRIFT-3336.

Here is an example:

{noformat}
namespace cpp example.detail

struct MyLower {
   1: binary lowerBinary
} (cpp.customostream)

struct MyHigher {
    1: set<Lower> lowers
}
{noformat}

The annotation {{cpp.customostream}} (or the compiler option {{--gen cpp:no_ostream_operators}} for global effect) tells the compiler to emit only the declaration of the {{operator <<}} but does not emit a definition (implementation).  It would be up to the implementation building against the generated code to provide an operator << if such an operator is needed for conversion to a stream (cout, lexical_cast to string, etc..).

  was:
I'm in the middle of converting a project that provides some ostream operators (for logging purposes) for a number of thrift structures.  The project was using 0.8.0 and in 0.9.3 some ostream operator overloads were added with THRIFT-3336.  The solution that was provided here runs into complications if a thrift structure is contained within another one.  Take this simple example:

h4. Thrift
{noformat}
namespace cpp example.detail

struct Lower {
   1: binary lowerBinary
}

struct Higher {
    1: set<Lower> lowers
}
{noformat}

h4. C++
{noformat}
namespace example {

class Lower : public detail::Lower
{
    virtual void printTo(std::ostream& os) const override;
}

class Higher : public detail::Higher
{
    virtual void printTo(std::ostream& os) const override
    {
        os << lowers;   // WHOOPS!
            // I cannot say os << lowers, since lowers is an example::detail concept
            // it will print the thrift operator output here
    }
}

}
{noformat}

I'm considering adding an anotation to the thrift IDL that the compiler will recognize that allows someone to say, "I am going to provide my own operator<< for this structure, don't generate one".

This will allow existing projects with this issue to maintain compatibility without major refactoring.  Here is an example:

{noformat}
namespace cpp example.detail

struct Lower {
   1: binary lowerBinary
} (cpp.customostream)

struct Higher {
    1: set<Lower> lowers
}
{noformat}

For Lower, this would omit any operator << by the compiler, and thus also would not emit a printTo override for Lower.  It would be up to the implementation building against the generated code to provide an operator <<.


> Thrift printTo ostream overload mechanism breaks down when types are nested
> ---------------------------------------------------------------------------
>
>                 Key: THRIFT-4060
>                 URL: https://issues.apache.org/jira/browse/THRIFT-4060
>             Project: Thrift
>          Issue Type: Bug
>          Components: C++ - Compiler
>    Affects Versions: 0.9.3, 0.10.0
>         Environment: Ubuntu 14.04 LTS
>            Reporter: James E. King, III
>            Assignee: James E. King, III
>
> I'm in the middle of converting a project that provides some ostream operators (for logging purposes) for a number of thrift structures.  The project was using 0.8.0 and in 0.9.3 some ostream operator overloads were added with THRIFT-3336.  The solution that was provided here runs into complications if a thrift structure is contained within another one.  Take this simple example:
> h4. Thrift
> {noformat}
> namespace cpp example.detail
> struct Lower {
>    1: binary lowerBinary
> }
> struct Higher {
>     1: set<Lower> lowers
> }
> {noformat}
> h4. C++
> {noformat}
> namespace example {
> class MyLower : public detail::Lower
> {
>     virtual void printTo(std::ostream& os) const override;
> }
> class MyHigher : public detail::Higher
> {
>     virtual void printTo(std::ostream& os) const override
>     {
>         os << lowers;
>         // here's the problem, lowers is a set<detail::Lower> when it serializes in,
>         // not a set<MyLower>, so I cannot override it...
>     }
> }
> }
> {noformat}
> I'm considering adding an annotation to the thrift IDL that the compiler will recognize that allows someone to say, "I am going to provide my own operator<< for this structure, don't generate one".  This would replace the printTo mechanism that was added in THRIFT-3336.
> Here is an example:
> {noformat}
> namespace cpp example.detail
> struct MyLower {
>    1: binary lowerBinary
> } (cpp.customostream)
> struct MyHigher {
>     1: set<Lower> lowers
> }
> {noformat}
> The annotation {{cpp.customostream}} (or the compiler option {{--gen cpp:no_ostream_operators}} for global effect) tells the compiler to emit only the declaration of the {{operator <<}} but does not emit a definition (implementation).  It would be up to the implementation building against the generated code to provide an operator << if such an operator is needed for conversion to a stream (cout, lexical_cast to string, etc..).



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)