tags:

views:

196

answers:

1

Currently, I am using a type-safe enum class from Boost Vault :

http://stackoverflow.com/questions/217549/which-typesafe-enum-in-c-are-you-using

I found it is difficult to have a parent class pointer to refer to all enum class, due to Boost::enum is a template class : boost::detail::enum_base<T>

I am using void fun(const boost::any& any), to accept any enum class. However, I need to cast them to an enum class before I perform iteration. I cannot cast to a base class boost::detail::enum_base<T>, as I do not have information on what T will be.

Any suggestion on how to solve this?

One of the requirement is that, the function argument must be in boost::any.

#include <iostream>
#include <boost/any.hpp>
#include "boost/enum.hpp"


// this macro
BOOST_ENUM(boolean, 
    (True)
    (False) 
)

// expands to this enum model
namespace expanded
{
    class boolean : public boost::detail::enum_base<boolean>
    {
    public:
     enum domain
     {
      False,
      True,
     };

     BOOST_STATIC_CONSTANT(index_type, size = 2);

    public:
     boolean() {}
     boolean(domain index) : boost::detail::enum_base<boolean>(index) {}

     typedef boost::optional<boolean> optional;
     static optional get_by_name(const char* str)
     {
      if(strcmp(str, "False") == 0) return optional(False);
      if(strcmp(str, "True") == 0) return optional(True);
      return optional();
     }

    private:
     friend class boost::detail::enum_base<boolean>;
     static const char* names(domain index)
     {
      BOOST_ASSERT(static_cast<index_type>(index) < size);
      switch(index)
      {
      case False: return "False";
      case True: return "True";
      default: return "";
      }
     }
    };
}

BOOST_ENUM(boolean2, 
    (True2)
    (False2) 
)

/* I want to have a function to accept any enum class. How? */
void fun(const boost::any& any)
{
    /* How about boolean2 enum? How can I have a common pointer to point to enum class? */
    const boolean* d = boost::any_cast<boolean *>(any);

    /* I want to use unofficial boost::enum, because it allows me to iterate through enum's members. */
    for (boolean::const_iterator iterator = d->begin(); iterator != d->end(); iterator++)
    {
        boolean x = *iterator;
        std::cout<< "Iterate through enum : "<< x<< std::endl;
    }
}


int main()
{
    boolean b = boolean::True;
    boolean2 b2 = boolean2::True2;

    /* Assume until this stage, during runtime, I have no clue b is either boolean or boolean2. */
    fun(&b);
    /*
     * Runtime error occur here.
     * throw enable_current_exception(enable_error_info(e));
     */
    fun(&b2);

    getchar();
}
+1  A: 

If the access is not possible through the base class, use function templates:

template<class TE> // should be a boost enum
void fun(TE& en)
{
    for (TE::const_iterator it = en.begin(); it != en.end(); ++it)
    {
        /* ... */
    }
}

As for a common base pointer:
You can't use one the way the boost enum is defined. It doesn't have a single base class, instead it has seperate base classes per enum type and per (optional) value type.
Also, the main point of the boost enum is static type-safety - if what you're asking is meant to work on different enum types based on runtime-decisions you are using the wrong tool.

update:
If you really have that immutable requirements, you could base explicit casting on boost::any::type, e.g. (utilizing the function template given above):

const std::type_info& ti = any.type();
if(ti == typeid(boolean*)) {
  fun(*boost::any_cast<boolean*>(any));
} else if(ti == typeid(boolean2*)) {
  /* ... */
}
Georg Fritzsche
but i have no clue at all, TE should be boolean or boolean2, during compile time.
Yan Cheng CHEOK
But that doesn't stop you from letting the compiler decide what type to use as e.g. here: `fun(boolean::True)`. You only need to know it provides `begin()` etc.
Georg Fritzsche
Yan Cheng CHEOK
I get ""could not deduce template argument for 'TE'""
Yan Cheng CHEOK
It needs to take a `boost::any` which can contain some arbitrary version of the boost enum? Sorry, but then its not possible without explicit conversion.
Georg Fritzsche
... the function template was meant to take an instance of the boost enum as parameter.
Georg Fritzsche