-1

I've two macros and I desire to convert them in C++ templates. I've problems in understendig how to convert them.

Here are the two macros:

#define __MATRIX_GETVALUE(C,T,val,dim0...) \
    va_list vl; \
    va_start(vl,dim0); \
    C->setPositions(vl,dim0); va_end(vl);\
    val = *((T *)(m_values)+posInValueVector())

#define __MATRIX_SETVALUE(C,T,val,dim0...) \
    va_list vl; \
    va_start(vl,dim0); \
    C->setPositions(vl,dim0); va_end(vl);\
    *((T *)(m_values)+posInValueVector())=val

The two macros above are used in the software in my first answer to this question.

Community
  • 1
  • 1
Sir Jo Black
  • 2,024
  • 2
  • 15
  • 22
  • 3
    Names with a double underscore are reserved for the compiler and standard library. You should not use them. See e.g. http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier – Some programmer dude May 03 '15 at 05:15
  • 1
    What did you try so far? – Potatoswatter May 03 '15 at 05:15
  • @Joachim Pileborg. May be they are reserved! But is not the point! Thanks for the suggestion! :) – Sir Jo Black May 03 '15 at 05:18
  • @Potatoswatter. I'm a C programmer more than a C++ programmer. In truth I want to study and understand templates to avoid the use of C style macros. But because I'm able to solve problems using #define ... :p – Sir Jo Black May 03 '15 at 05:22
  • I see that more than to give an help, some people downvotes ... Thank you! :) – Sir Jo Black May 03 '15 at 05:28

1 Answers1

1

With C++11 and variadic template you can get n-dimensional matrices easily with for example:

template<typename T, int ...rest>
struct matrix;

template<typename T, int n>
struct matrix<T, n> {
    T data[n];
    matrix() {
        for (int i=0; i<n; i++) {
            data[i] = T(0);
        }
    }
    T& operator[](int index) { return data[index]; }
};

template<typename T, int n, int ...rest>
struct matrix<T, n, rest...> {
    matrix<T, rest...> data[n];
    matrix<T, rest...>& operator[](int index) { return data[index]; }
};

that can be used with:

matrix<double, 10, 9, 4> m;
for (int i=0; i<10; i++) {
    for (int j=0; j<9; j++) {
        for (int k=0; k<4; k++) {
            m[i][j][k] = i + j*2.718 + k*3.1416;
        }
    }
}

without the problems of the horrible macros you have now:

  • reserved names
  • regular names injection
  • multiple evaluation of arguments
  • variadic C function calls
  • use of matrix object state for "current position"
6502
  • 112,025
  • 15
  • 165
  • 265
  • But is it possible to use it has matrix? I've to understand this kind of objects! The code where are the orrible macros manages whatever you want number of dimensions! – Sir Jo Black May 03 '15 at 05:48
  • The code shown works for `matrix`: it's not about two-dimensional matrix, but n-dimensional... – 6502 May 03 '15 at 05:52
  • But with your template how can I indicate that I want m[i][j][k]? – Sir Jo Black May 03 '15 at 06:00
  • @SergioFormiggini: See edited example. The idea of the code is that you define a specialization for unidimensional matrices (i.e. arrays) where data is just a C++ array, and a specialization for n-dimensional matrices (n>1) where data is an (n-1)-dimensional matrix. Template metaprogramming is annoyingly intricate because you cannot for example do regular loops, but you need to use recursion instead. – 6502 May 03 '15 at 06:03
  • All ok! It's perfect! Thank you very much! :) I've written the same as in your edit, but with an error in a for :p ... :) – Sir Jo Black May 03 '15 at 06:05
  • Another question! I still don't understand how and where the templates you indicate me stores the values. Am I able to retrieve a pointer to the whole matrix area with the purpose to save it on a file? Or is the solution to save element per element on a file? – Sir Jo Black May 03 '15 at 06:11
  • I would like to upvote your solution more than one time. I think is the better and demonstrate me the power of C++! – Sir Jo Black May 03 '15 at 06:13
  • @SergioFormiggini: `data` member is going to contain the data and in compilers I know it would contain just the elements and possibly padding. Note however that formally the data is composed in this example of class instances and you're not expected to access object bytes directly. Working element-by-element is the correct way to do it in this case. – 6502 May 03 '15 at 06:16
  • Using this code: cout << &m[i][j][k] << endl; I see that there's no padding and the data are contiguous. ... But if data are class instances ... Obviously I've to imagine that this code uses dynamic allocation! (but this is another question!) – Sir Jo Black May 03 '15 at 06:19
  • Anyway you has been very precious! Thanks a lot! :) – Sir Jo Black May 03 '15 at 06:22