Click here to Skip to main content
15,896,726 members
Articles / Programming Languages / C++

Enumerator Lists and Enumerated Arrays

Rate me:
Please Sign up or sign in to vote.
4.60/5 (9 votes)
4 Oct 2011CPOL11 min read 59.2K   464   15  
Establishing a strong binding between enumerations and arrays
// This file is part of EnumeratorLib
// Copyright: Andreas Raczek
// This file is published under the The Code Project Open License (CPOL) 
// See the file "CPOL.html" for the full license governing this code. 
#pragma once

namespace lobster {

namespace enm {

#ifdef ENUMERATORLIB_VS2008HACK
template<typename enum_array, typename enum_type>
#else
template<typename enum_array>
#endif
struct default_value :
    private enum_array
{
    typedef typename enum_array::enum_list  enum_list;
    typedef typename enum_array::value_type value_type;
    
    // If this definition is used, VC2008SP1 crashes when
    // compiling the default_value<...>::value<...>() 
    // method template.
#ifndef ENUMERATORLIB_VS2008HACK
    typedef typename enum_array::enum_type  enum_type;   
#endif
    
    static const int size = enum_array::size;


#pragma region Constructors
    default_value() {};
    
    template<typename input_iterator>
    default_value(input_iterator first, input_iterator last)
        : enum_array(first, last)
    {
    }
    
    template<typename pair_type, int n>
    default_value(const pair_type(&arr)[n]) 
    {
        // Test if the supplied array size matches the one of
        // the enumerator list + 1 for the default value
        static_assert<n == size + 1>();
        
        for(size_t i = 0; i < n; i++) {
            (*this)[arr[i].first] = arr[i].second;
        }   
    }
#pragma endregion

#pragma region Element accessors
    // Default value storage
    value_type defaultvalue;

private:
    // value() helper delivering default value when bool == false
    template<typename enum_array, bool b>
    struct _value_helper {
        typedef typename copy_const<enum_array, typename enum_array::value_type>::type value_type;
        
        template<
            typename enum_array::enum_type enum_value_test
        > 
        inline static typename value_type& value(enum_array& /* obj */, value_type& default_value) {
            return default_value;
        }
    };
    
    // value() helper delivering correct value when bool == true
    template<typename enum_array>
    struct _value_helper<
        enum_array,
        true
    > {
        typedef typename copy_const<enum_array, typename enum_array::value_type>::type value_type;
        
        template<
            typename enum_array::enum_type enum_value_test
        > 
        inline static value_type& value(enum_array& obj, value_type& /* default_value */) {
            return obj.value<enum_value_test>();
        }
    };

public:
    // Compile-time element accessor
    template<enum_type enum_value_test>
    inline value_type& value() 
    {
        return _value_helper<
                enum_array,
                index_of<typename enum_array::enum_list, enum_value_test>::value >= 0
            >::value<
                enum_value_test
            >(
                (enum_array&) (*this), default_value
        );
    }

    // Compile-time const accessor
    template<enum_type enum_value_test>
    inline const value_type& value() const
    {
        return _value_helper<
                const enum_array, 
                index_of<typename enum_array::enum_list, enum_value_test>::value >= 0
            >::value<
                enum_value_test
            >(
                (const enum_array&) (*this), defaultvalue
        );
    }

    
    // run-time element accessor override
    inline value_type& operator[](enum_type enum_value_test) {
        return enum_list::index_of(enum_value_test) >= 0 ?
            enum_array::operator[](enum_value_test)
                :
            defaultvalue;
    }
    
    // run-time const accessor
    inline const value_type& operator[](enum_type enum_value_test) const {
        return const_cast<const value_type&>(
            const_cast<default_value*> (this)->operator[](enum_value_test)
        );
    }
#pragma endregion
};

}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions