5

I'm currently trying to do a complicated variable correction to a bunch of variables (based on normalizing in various phase spaces) for some data that I'm reading in. Since each correction follows the same process, I was wondering if there would be anyway to do this iteratively rather than handle each variable by itself (since I need to this for about 18-20 variables). Can C++ handle this? I was told by someone to try this in python but I feel like it could be done in C++ in some way... I'm just hitting a wall!

To give you an idea, given something like:

class VariableClass{
    public :
      //each object of this class represents an event for this particlular data set 
      //containing the following variables
      double x;
      double y;
      double z;
}

I want to do something along the lines of:

for (int i=0; i < num_variables; i++)
{
   for (int j=0; j < num_events; j++)
   {
     //iterate through events
   }
   //correct variable here, then move on to next one
}

Thanks in advance for any advice!!!

Wakka Wakka Wakka
  • 271
  • 1
  • 9
  • 16
  • 2
    You mean like an array? – chris Feb 25 '13 at 20:34
  • 2
    This is an interesting question. I'm kind of curious about what responses you'll get myself. I can't help but wonder if you'll run into difficulties identifying variable types. For example, it seems easy to see the contents of an object in memory, but how do you know that the first variable in the object is a double? I look forward to the responses for this question. – Kirby Feb 25 '13 at 20:37
  • 1
    Are all variables doubles ? Are their number fixed ? Then use `std::array` or a plain old `double[18]`. – BatchyX Feb 25 '13 at 20:44
  • One thing people are not mentioning here is, no, unlike some scripting languages, there isn't a way to enumerate random types of member variables in C++. Intimate knowledge of the structure is required to manipulate those values. – cppguy Feb 25 '13 at 20:56

5 Answers5

3

I'm assuming your member variables will not all have the same type. Otherwise you can just throw them into a container. If you have C++11, one way you could solve this problem is a tuple. With some template metaprogramming you can simulate a loop over all elements of the tuple. The function std::tie will build a tuple with references to all of your members that you can "iterate" like this:

struct DoCorrection
{
    template<typename T>
    void operator()(T& t) const { /* code goes here */ }
};

for_each(std::tie(x, y, z), DoCorrection());
// see linked SO answer for the detailed code to make this special for_each work.

Then, you can specialize operator() for each member variable type. That will let you do the appropriate math automatically without manually keeping track of the types.

Community
  • 1
  • 1
Michael Kristofik
  • 34,290
  • 15
  • 75
  • 125
2

taken from glm (detail vec3.incl)

template <typename T>
GLM_FUNC_QUALIFIER typename tvec3<T>::value_type & 
tvec3<T>::operator[]
(
    size_type i
)
{
    assert(i < this->length());
    return (&x)[i];
}

this would translate to your example:

class VariableClass{
public :
  //each object of this class represents an event for this particlular data
  double x;
  double y;
  double z;

  double & operator[](int i) {
    assert(i < 3);
    return (&x)[i];
  }
}

VariableClass foo();
foo.x = 2.0;
std::cout << foo[0] << std::endl; // => 2.0

Althought i would recomment glm, if it is just about vector math.

scones
  • 3,317
  • 23
  • 34
  • 4
    this is very unsafe. You are not guaranteed your compiler won't pad your data to make it more efficiently accessible. You should at least add a `#pragma pack(1)` or something in this flavour. – Qortex Feb 25 '13 at 20:46
  • That's why i recommend the library. The library is tested. And i am just showing this as an alternative to the std containers, in case he needs the access via `foo.x` as well. And yes, you are right, it is unsafe. – scones Feb 25 '13 at 20:50
1

Yes, just put all your variables into a container, like std::vector, for example.

piokuc
  • 25,594
  • 11
  • 72
  • 102
  • 2
    Or `std::tuple`, if they have varying types. – BatchyX Feb 25 '13 at 20:38
  • Yes, but it doesn't look like it is the case here, does it? – piokuc Feb 25 '13 at 20:39
  • 1
    See, I was trying to think of how to use a vector for this... but how exactly would I implement it? Perhaps I would need to loop through my events and variables in a different way than stated above. But it's more tricky then simply making a vector. Or maybe i'm overcomplicating this – Wakka Wakka Wakka Feb 25 '13 at 20:42
  • Actually, I figured it out how to vectorize it. Not so hard after all. Thanks for the suggestion! – Wakka Wakka Wakka Feb 25 '13 at 20:54
1

http://en.cppreference.com/w/cpp/container/vector

I recommend spending some time reading about all the std classes. There are many containers and many uses.

Griwes
  • 8,805
  • 2
  • 43
  • 70
Joy
  • 321
  • 1
  • 9
0

In general you cannot iterate over members without relying on implementation defined things like padding or reordering of sections with different access qualifiers (literally no compiler does the later - it is allowed though).

However, you can use a the generalization of a record type: a std::tuple. Iterating a tuple isn't straight-forward but you will find plenty of code that does it. The worst here is the loss of named variables, which you can mimic with members.

If you use Boost, you can use Boost.Fusion's helper-macro BOOST_FUSION_ADAPT_STRUCT to turn a struct into a Fusion sequence and then you can use it with Fusion algorithms.

pmr
  • 58,701
  • 10
  • 113
  • 156