C++11 Fun with initializer lists, arrays, and enumerations

后端 未结 5 1748
天涯浪人
天涯浪人 2021-01-03 03:27

Background

C++11 initializer lists can be used to initialize vectors and arrays with argument passing to constructors.

I have a piece of code below

5条回答
  •  失恋的感觉
    2021-01-03 03:39

    I like your problem. Long ago, this kind of thing used to be handled with X macros http://www.drdobbs.com/the-new-c-x-macros/184401387

    I'm a c++11 newb, but after some fiddling around I've got some kind of solution (g++ 4.8.4):

    enum class Symbols { FOO, BAR, BAZ, First=FOO, Last=BAZ };
    

    I kept your Size() but added some other boilerplate to make the initialization, lower down, easier to read.

    template< typename E > constexpr size_t Size() { return (size_t)(E::Last) - (size_t)(E::First) + 1; }
    template< typename E > constexpr size_t as_sizet( E s ) { return (size_t)s; }
    template< typename E > constexpr E operator++( E& s, int ) { return (E)(1 + (size_t)s); }
    template< typename E > constexpr bool operator<=( E& a, E& b ) { return (size_t)a < (size_t)b; }
    

    There are two bits of magic here:

    • We return a reference to the initialized array (itself another template parameter)
    • We initialize a static array during the recursive call using a junk argument

    Like so:

    template< typename E, typename EARR > 
    constexpr EARR& init_array( EARR& zArr, E sym = E::First, E junk = E::Last )
    {
        return sym <= E::Last ? init_array( zArr, sym++, zArr[ as_sizet( sym ) ] = sym ) : zArr;
    }
    

    In the end, it comes together with:

    • The typedef
    • The static declaration of the array
    • The reference to the array that gets initialized

    Like so:

    typedef Symbols SymbolArr[ Size() ];
    static SymbolArr symbolArr;
    SymbolArr& symbolArrRef = init_array(symbolArr);
    

    Edit:

    The junk parameter in the recursive initialization function can be removed using:

    template< typename E > constexpr E next( E& s ) { return (E)(1 + (size_t)s); }
    
    template< typename E, typename EARR > 
    constexpr EARR& init_array( EARR& zArr, E sym = E::First )
    {
        return sym <= E::Last ? init_array( zArr, next( zArr[ as_sizet( sym ) ] = sym ) ) : zArr;
    }
    

提交回复
热议问题