Search code examples
c++thrift

C++ Brace Initialization for Thrift-Generated Structures


I'm using Thrift w/C++ and it generates a number of structures with constructors like the ones below:

struct ThriftColor
{
  ThriftColor(const ThriftColor&);
  ThriftColor& operator=(const ThriftColor&);
  ThriftColor() : color((ZColor::type)0), duration(0) { }

  ZColor::type color;
  int32_t duration;
};

I haven't been able to figure out how to brace initialize this.

The error I get is:

error: could not convert '{RED, 1000}' from '<brace-enclosed initializer list>' to 'ThriftColor'

Or when using a vector:

error: could not convert '{{RED, 1000}, {GREEN, 2000}}' from '<brace-enclosed initializer list>' to 'std::vector<ThriftColor>'

A similar form of the structure, works:

struct TimedColor
{
    TimedColor(ZColor::type c, int d) : color(c), duration(d) {}
    ZColor::type color;
    int duration;
};

Is there a way to get Thrift to generate a structure that can be brace-initialized? And/or: Is there a way to brace initialize the first structure?

Thanks in advance!

Full Example: http://cpp.sh/3wgq

// Example program
#include <iostream>
#include <string>
#include <vector>

struct ZColor {
enum type {
    OFF,
    RED,
    GREEN,
    YELLOW,
    BLUE,
    MAGENTA,
    CYAN,
    WHITE
};
};


struct TimedColor
{
    TimedColor(ZColor::type c, int d) : color(c), duration(d) {}
    ZColor::type color;
    int duration;
};

struct ThriftColor
{
  ThriftColor(const ThriftColor&);
  ThriftColor& operator=(const ThriftColor&);
  ThriftColor() : color((ZColor::type)0), duration(0) { }

  ZColor::type color;
  int32_t duration;
};

template<typename T>  
void Dump( std::vector<T>& vec)
{
    for(typename std::vector<T>::iterator it = vec.begin(); it != vec.end(); it++)
    {
        std::cout << it->color << ":" << it->duration << std::endl;
    }
}

void TestFunction1()
{
    std::vector<TimedColor> vec;
    vec.push_back(TimedColor(ZColor::RED,1000));
    vec.push_back(TimedColor(ZColor::GREEN,2000));
    Dump(vec);    
}

void TestFunction2()
{
    std::vector<TimedColor> vec = { { ZColor::RED, 1000 }, { ZColor::GREEN, 2000 } };
    Dump(vec);    
}

void TestFunction3()
{
    // fails
    ThriftColor tc =  { ZColor::RED, 1000 };
    std::vector<ThriftColor> vec = { { ZColor::RED, 1000 }, { ZColor::GREEN, 2000 } };
    Dump(vec);    
}

int main()
{
  TestFunction1();
  TestFunction2();
  TestFunction3();
}

Solution

  • It turns out it's not currently possible to generate complex structures that can be brace-initialized with Thrift. Upon further consideration this is probably a Good Thing as Thrift generates methods for setting members of structures that keep track of whether optional fields are set. For example, Thrift might generate this:

    void ThriftColor::__set_duration(const int32_t val) {
      this->duration = val;
    __isset.duration = true;
    }
    

    It would be fairly complex to generate a non-trivial structure that could correctly set the internal __isset structures from brace-initialization.

    In the end, I created a helper function that initializes my ThriftColor vectors for me and use them to build out the ThriftObject.