c++c++11c++14variadic-functionsindex-sequence

How to iterate over std::index_sequence


I have this code in my source:

template <std::size_t... Dims>
class DimensionPack {
public: 
    using Dimensions = std::index_sequence<Dims...>;
    static const std::size_t total_dimensions = sizeof...(Dims);
    std::vector<unsigned int> even_or_odd;

public:
    DimensionPack() {
        unsigned idx = 0;
        for ( ; idx < total_dimensions; idx++ ) {
            //MatrixDimensionOddOrEven mdoe( Dimensions[idx] );
            //unsigned int val = mdoe.even_or_odd;
            //even_or_odd.push_back( val );
        }
    }
};

The commented lines of code is the code in question. I'm not familiar with using std::indx_sequence<> and I've read the documentation from MSD on it and still not sure about it especially when it is used with the using directive.

This template class will be used as a parameter pack for other variadic template classes for storing and extracting the data from the variadic parameter list. Within this class's constructor I'm using this structure's constructor and private method to check values and to return its state of either being even or odd and getting the value from its public constant member:

struct MatrixDimensionOddOrEven {
    const unsigned int even_or_odd; 
    explicit MatrixDimensionOddOrEven( unsigned int odd_or_even ) : even_or_odd( test( odd_or_even ) ) {}

private:
    const unsigned int test( unsigned int value ) const {
        if ( value == 0 ) {
            std::ostringstream strStream;
            strStream << __FUNCTION__ << "invalid number: " << value << " must be >= 1.";
            Logger::log( strStream, Logger::TYPE_ERROR );
            throw ExceptionHandler( strStream );
        }
        return ( ((value % 2) == 0) ? ODD : EVEN );
    }
};

The cpp file to this header file compiles, but when I go to compile another cpp file such as main that includes it; it fails to compile.

This is the current error messages that I'm getting:

1>------ Build started: Project: FileTester, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\skilz80\documents\visual studio 2015\projects\filetester\filetester\matrix.h(44): error C2540: non-constant expression as array bound
1>  c:\users\skilz80\documents\visual studio 2015\projects\filetester\filetester\matrix.h(41): note: while compiling class template member function 'DimensionPack<2,3,4>::DimensionPack(void)'
1>  c:\users\skilz80\documents\visual studio 2015\projects\filetester\filetester\main.cpp(336): note: see reference to function template instantiation 'DimensionPack<2,3,4>::DimensionPack(void)' being compiled
1>  c:\users\skilz80\documents\visual studio 2015\projects\filetester\filetester\matrix.h(60): note: see reference to class template instantiation 'DimensionPack<2,3,4>' being compiled
1>  c:\users\skilz80\documents\visual studio 2015\projects\filetester\filetester\main.cpp(155): note: see reference to class template instantiation 'Matrix<float,2,3,4>' being compiled
1>c:\users\skilz80\documents\visual studio 2015\projects\filetester\filetester\matrix.h(45): error C2228: left of '.even_or_odd' must have class/struct/union
1>c:\users\skilz80\documents\visual studio 2015\projects\filetester\filetester\matrix.h(45): error C2789: 'val': an object of const-qualified type must be initialized
1>  c:\users\skilz80\documents\visual studio 2015\projects\filetester\filetester\matrix.h(45): note: see declaration of 'val'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

It isn't so much the compiler errors that are giving me trouble; it is more about this syntax that is sort of new to me within the use of variadic templates and parameter packs. So how do I properly write the syntax to get the individual elements of this std::index_sequence<...> that is assigned to Dimensions with the using directive in order to pass those values to the constructor of the helper structure that is seen in the for loop within the DimensionPack class?


Solution

  • There is no need for index_sequence. This will do:

    template <std::size_t... Dims>
    class DimensionPack {
    public:
        std::vector<unsigned int> even_or_odd;
    
    public:
        DimensionPack()
            : even_or_odd{MatrixDimensionOddOrEven{Dims}.even_or_odd...}
        {
        }
    };
    

    As a bonus, the beauty of it is that you don't need to push_back each element. You can directly initialize the vector with all the elements.