2


suppose I have a class

class CAT  
{  
private:  
  int a;  
  long b;  
  double c;    
  string d;  
};    

now I need a function which can initialize all the members to a specific value, for example:

  • int set to 0
  • long set to -1
  • double set to -1.1
  • string set to unknown

so far, I can write a function named initMembers:

void initMembers()   
{   
    a = 0;   
    b = -1;   
    c = -1.1;   
    d = "unknown";   
}   

but if I have 1000 classes like CAT, and some of them have 4 members, some of them have 40 members,..... so I have to write an initMember functuions for every class.

I wonder if there is way can traversed all the members inside a class?

Thanks advance for your help!

I mean I want initialize specific type with a corresponding value

for all members inside all classes

* int set to 0
* long set to -1
* double set to -1.1
* string set to unknown
camino
  • 10,085
  • 20
  • 64
  • 115
  • 1
    Are you just asking out of curiosity, or do you actually have a case where you need to do something like this? – Laurence Gonsalves Dec 16 '10 at 07:36
  • 1
    See this related question: http://stackoverflow.com/q/3930841/57428 and the accepted answer to it - it might be helpful to you. – sharptooth Dec 16 '10 at 07:38
  • 1
    @sharptooth: Does that question really apply, though? `-1`, `-1.1` and `"unknown"` are all different from what value initialization would give you and all different from each other. I suppose you could explicitly specialize the `initialized` template for every type. – CB Bailey Dec 16 '10 at 07:43
  • @Charles Bailey: Yes, it does partially apply, since C++ doesn't have reflection and one can write template specializations and actully solve the problem this way. It won't be nice, but it'll work. – sharptooth Dec 16 '10 at 07:47

6 Answers6

3

No. C++ doesn't have reflection.

Laurence Gonsalves
  • 137,896
  • 35
  • 246
  • 299
3

May I suggest you a C++ book? I think you are missing some basic about this language.

  1. you can only have one class named CAT, not thousands of them. You can have thousands of instances of it, that's a whole different thing.

  2. You use class constructors to do what you are doing in initMembers() function:

    class CAT  
    {  
    public:  
        CAT(): a(0), b(-1), c(-1.1), d("unknown") { }
    
    
    private:  
      int a;  
      long b;  
      double c;    
      string d;  
    }; 
    
  3. C++ doesn't have reflection, so there's no way to "traverse" its members.

icecrime
  • 74,451
  • 13
  • 99
  • 111
Simone
  • 11,655
  • 1
  • 30
  • 43
2

Just an idea of what can be done with Boost.Fusion :

#include <iostream>
#include <string>

#include <boost/fusion/adapted/struct/define_struct.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/lambda/lambda.hpp>

BOOST_FUSION_DEFINE_STRUCT
(
    /* namespace */,
    CAT,
    (int, a)
    (long, b)
    (double, c)
    (std::string, d)
)

struct initializer
{
    void operator()(int &v) const { v = 1; }
    void operator()(long &v) const { v = -1; }
    void operator()(double &v) const { v = 1.1; }
    void operator()(std::string &v) const { v = "unknown"; }
};

int main() 
{
    CAT c;
    boost::fusion::for_each(c, initializer());
    boost::fusion::for_each(c, std::cout << boost::lambda::_1 << ' ');
    std::cout << std::endl;
}

Outputs :

1 -1 1.1 unknown
icecrime
  • 74,451
  • 13
  • 99
  • 111
2

As all answers have said, there is no reflection in C++. And if you have 1000s of unique classes (not instances), then it's painful to have to write the same boiler plate code (such as ctors/dtors, may be streaming operations etc.)

When I face something like this, I always take a step back. First, rather than steaming a head and writing out all the C++ code for each class, I create an xml document which has all the structures, for example, let's say I have two structs, I'll create something like:

<classet>
<struct name="some_struct_a">
  <field type="int" name="foo"/>
  <field type="int" name="foo2"/>
  <field type="long" name="bar"/>
  <field type="std::string" name="bar2"/>
</struct>
<struct name="some_struct_b">
  <field type="int" name="foo"/>
  <field type="int" name="foo2"/>
</struct>
</classet>

Once that's done, I create an xslt (and you don't need to be a next level guru at xsl to do this), to generate the C++ code from the above xml. So, if you ever need to add any method to all your classes for example, you modify the xsl and re-generate, same goes for modifying any of the structures, modify the xml and re-generate. Once you get the xml and xslt ready, the change cycle is very quick.

Btw. before you scoff, lot's of exchanges (financial) provide xml documents describing message formats for this exact reason, some of these define a large number of messages in xml, and some have very large number of members.

Nim
  • 33,299
  • 2
  • 62
  • 101
  • Once you've come so far to realize, that C++ doesn't offer critical features like reflection and introspection and instead use XML for class representation, you might as well use it to generate the boilerplate code for using it in something like GObject. – datenwolf Dec 16 '10 at 09:10
  • Using XSLT is a clever idea. I did something similar, but used "// = 0" like comments after each member and then made a Perl script to generate actual constructors, getters and setters. – Sergei Tachenov Dec 16 '10 at 09:22
1

We use a hack in our code to auto-initialize data members in the code:

#define member(type, name, initval)
class class_ ## name { \
  type data;
  inline class_ ## name() : data(initval) {};\
  inline type operator()() const { return data; };\
  inline void operator(type newval) { data=newval; };\
};

And then, in any class:

class CAT {
  private:  
  member(int, a, 0);  
  member(long, b, -1);  
  member(double, c, -1.1);    
  member(string, d, "unknown"); 
  void foo() {
    d("newstring");  // set
    int aval=a();  // access
  };
};

You can tune the above macro and add some other neat functionality. However, for existing code, this means some amount of restructuring/rewrite.

0

You probably want to build an source code generation tool which translates some data document about what classes you need into C++ class declaration code. E.g. if you want to have a class for every animal and you have some digital literature about the animals, create a tailored tool to parse the animal book, filter the animal names and create class boilerplate code from it.