Search code examples
c++templatesstatic-membersvariadicstdarray

Assigning integer values from variadic template list to static const std::array member


Consider the following code snippet:

template<unsigned... IDs>
class MyClass{
public:
    static const std::array<unsigned, sizeof...(IDs)> ids { IDs... };
    PinIDs() = default;
};

Then use the class as:

MyClass<1,5,7,9> myClass;

The Objective would be to have ids with a size of 4, and contain the values: (1,5,7,9) respectively.

Is this type object possible or would I have to remove the static qualifier? If not how would one write this with the static qualifier. The object needs to be default constructible.


EDIT:

I tried Apple Apple's first solution and with MS Visual Studio 2017 CE on Win7 I got this compiler error:

 1>------ Build started: Project: PracticeMath, Configuration: Debug Win32 ------
1>stdafx.cpp
1>PracticeMath.cpp
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(33): error C2988: unrecognizable template declaration/definition
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(33): error C2143: syntax error: missing ';' before '<'
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(33): error C2059: syntax error: '<'
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(33): error C2039: 'ids': is not a member of '`global namespace''
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(33): error C2143: syntax error: missing ';' before '{'
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(33): error C2447: '{': missing function header (old-style formal list?)
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(38): error C2065: 'myId': undeclared identifier
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(39): error C2065: 'myId': undeclared identifier
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(40): error C2065: 'myId': undeclared identifier
1>c:\users\skilz80\documents\visual studio 2017\projects\practicemath\practicemath\practicemath.cpp(44): error C2065: 'c': undeclared identifier
1>Done building project "PracticeMath.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

With full original source like this:

#include <iostream>
#include <array>

template<unsigned... IDs>
class PinIDs{
public:
    static const std::array<unsigned, sizeof...(IDs)> ids;

    PinIDs() = default;

    const unsigned& operator[]( unsigned idx ) const {
        return ids[idx];
    }
};

template<unsigned... IDs>
const std::array<unsigned, sizeof...(IDs)> PinIDs<IDs...>::ids { IDs... };

int main() {
    PinIDs<4, 17, 19> myId;

    std::cout << myId[0] << " ";
    std::cout << myId[1] << " ";
    std::cout << myId[2] << " ";

    std::cout << "\nPress any key and enter to quit." << std::endl;
    char c;
    std::cin >> c;

    return 0;
}

Thanks to StoryTeller bringing up the fact that when I tried to apply Apple Apple's 1st method I accidently mixed up MyClass as opposed to the actual name of the class in my solution - project. Once I corrected that it does compile, build and run as expected.


Solution

  • you can try this


    #include <array>
    
    template<unsigned... IDs>
    class MyClass{
    public:
       static const std::array<unsigned, sizeof...(IDs)> ids;
       MyClass() = default;
    };
    
    template<unsigned... IDs>
    const std::array<unsigned, sizeof...(IDs)> MyClass<IDs...>::ids {IDs...};
    
    int main(){
       MyClass<1,5,7,9> myClass;
       return myClass.ids[0];
    }
    

    or use constexpr/inline (both need c++17)


    #include <array>
    template<unsigned... IDs>
    class MyClass{
    public:
        //static constexpr std::array<unsigned, sizeof...(IDs)> ids{IDs...};//or this
        static inline const std::array<unsigned, sizeof...(IDs)> ids{IDs...};
        MyClass() = default;
    };
    
    int main(){
    MyClass<1,5,7,9> myClass;
        return myClass.ids[0];
    }