是否可以定义 enumalpha ?

发布于 2024-08-27 18:38:18 字数 136 浏览 2 评论 0 原文

我希望能够写:

cout << enumalpha << Monday;

上打印:

星期一

并在控制台 Monday 是一个枚举类型。

I would like to be able to write:

cout << enumalpha << Monday;

and get printed on console:

Monday

P.S. Monday is an enum type.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傲鸠 2024-09-03 18:38:18

好吧,让我们开始所有预处理器:)

预期的使用方式:

DEFINE_ENUM(DayOfWeek, (Monday)(Tuesday)(Wednesday)
                       (Thursday)(Friday)(Saturday)(Sunday))

int main(int argc, char* argv[])
{
  DayOfWeek_t i = DayOfWeek::Monday;
  std::cout << i << std::endl;            // prints Monday

  std::cin >> i >> std::endl;             // reads the content of a string and
                                          // deduce the corresponding enum value
}

黑魔法,涉及有用的 Boost.Preprocessor 库。

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/for_each.hpp>

#define DEFINE_ENUM_VAL_TO_STR(r, data, elem)                      \
   case BOOST_PP_CAT(data, BOOST_PP_CAT(::, elem)):                \
    return out << BOOST_PP_STRINGIZE(elem);

#define DEFINE_ENUM_STR_TO_VAL(r, data, elem)                      \
   if (s == BOOST_PP_STRINGIZE(elem))                              \
   { i = BOOST_PP_CAT(data, BOOST_PP_CAT(::, elem)) ; } else


#define DEFINE_ENUM(Name, Values)                                  \
   struct Name {                                                   \
     enum type {                                                   \
       Invalid = 0,                                                \
       BOOST_PP_SEQ_ENUM(Values)                                   \
     };                                                            \
   };                                                              \
   typedef Name::type Name##_t;                                    \
   std::ostream& operator<<(std::ostream& out, Name##_t i) {       \
    switch(i) {                                                    \
      BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_VAL_TO_STR, Name, Values)  \
    default: return out << "~"; } }                                \
   std::istream& operator>>(std::istream& in, Name##_t& i) {       \
     std::string s; in >> s;                                       \
     BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_STR_TO_VAL, Name, Values)   \
     { i = Name##::Invalid; } }

有更好的方法,我个人使用这个小宏将所有内容存储在一个很好排序的成对向量中,对于类型来说是静态的,如果心情(或需要)发生,它还允许我迭代枚举的值:)

尽管该语言不支持这一点,但非常不幸。我希望如果有的话,枚举对于代码集来说非常方便......

Okay, let's go all preprocessor then :)

Intended way of use:

DEFINE_ENUM(DayOfWeek, (Monday)(Tuesday)(Wednesday)
                       (Thursday)(Friday)(Saturday)(Sunday))

int main(int argc, char* argv[])
{
  DayOfWeek_t i = DayOfWeek::Monday;
  std::cout << i << std::endl;            // prints Monday

  std::cin >> i >> std::endl;             // reads the content of a string and
                                          // deduce the corresponding enum value
}

Dark magic, involving the helpful Boost.Preprocessor library.

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/for_each.hpp>

#define DEFINE_ENUM_VAL_TO_STR(r, data, elem)                      \
   case BOOST_PP_CAT(data, BOOST_PP_CAT(::, elem)):                \
    return out << BOOST_PP_STRINGIZE(elem);

#define DEFINE_ENUM_STR_TO_VAL(r, data, elem)                      \
   if (s == BOOST_PP_STRINGIZE(elem))                              \
   { i = BOOST_PP_CAT(data, BOOST_PP_CAT(::, elem)) ; } else


#define DEFINE_ENUM(Name, Values)                                  \
   struct Name {                                                   \
     enum type {                                                   \
       Invalid = 0,                                                \
       BOOST_PP_SEQ_ENUM(Values)                                   \
     };                                                            \
   };                                                              \
   typedef Name::type Name##_t;                                    \
   std::ostream& operator<<(std::ostream& out, Name##_t i) {       \
    switch(i) {                                                    \
      BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_VAL_TO_STR, Name, Values)  \
    default: return out << "~"; } }                                \
   std::istream& operator>>(std::istream& in, Name##_t& i) {       \
     std::string s; in >> s;                                       \
     BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_STR_TO_VAL, Name, Values)   \
     { i = Name##::Invalid; } }

There are better ways, personally I use this little macro to store that all in a nicely sorted vector of pairs, static for the type, it also allows me to iterate through the values of the enum if the mood (or need) strikes :)

It's quite unfortunate though there is no support in the language for that. I would prefer if there was, enum are quite handy for codesets...

我要还你自由 2024-09-03 18:38:18

据我所知,你想要的确切形式是不可能的。正如尼尔所说,名字是为我们人类而存在的。编译器处理这些值。

也就是说,您可以创建一个实用程序来为枚举命名。这是一个示例:

#define ENUM_NAMES_BEGIN(pType) \
    std::ostream& operator<<(std::ostream& pStream, pType pValue) \
            { \
                switch (pValue) \
                {

#define ENUM_NAMES_CASE_NAMED(pValue, pName) \
                case (pValue): \
                    pStream << (pName); \
                    break;

#define ENUM_NAMES_CASE(pValue) ENUM_NAMES_CASE_NAMED(pValue, #pValue)

#define ENUM_NAMES_END(pDefault) \
                default: \
                    pStream << (pDefault); \
                } \
                \
                return pStream; \
            }

您可以这样使用它:

#include <iostream>

enum Days
{
    Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
};

enum NotNamed
{
    DontTry, ImNotnamed
};

ENUM_NAMES_BEGIN(Days)
    ENUM_NAMES_CASE(Sunday)
    ENUM_NAMES_CASE(Monday)
    ENUM_NAMES_CASE(Tuesday)
    ENUM_NAMES_CASE(Wednesday)
    ENUM_NAMES_CASE(Thursday)
    ENUM_NAMES_CASE(Friday)
    ENUM_NAMES_CASE_NAMED(Saturday, "Saturday: Fun day!")
ENUM_NAMES_END("")

int main()
{
    Days d = Saturday; // or whatever
    NotNamed n = ImNotnamed;

    std::cout << "Day: " << d << std::endl;
    std::cout << "Not Named: " << n << std::endl;
}

尝试使用“未命名”的类型返回其数值。

请注意,这里实际上没有任何枚举的强制执行;例如,您可以使用它来命名整数值。如果这样做,operator<< 将是不明确的。

如果您可以使用 Boost,请使用其类型特征 is_enum (相当复杂)并静态断言情况如此。为此,更改将是:

#include <boost/static_assert.hpp>
#include <boost/type_traits/is_enum.hpp>

#define ENUM_NAMES_BEGIN(pType) \
    std::ostream& operator<<(std::ostream& pStream, pType pValue) \
            { \
                BOOST_STATIC_ASSERT(boost::is_enum<pType>::value); \
                switch (pValue) \
                {

现在,如果类型不是枚举,则编译错误至少指向您尝试定义枚举名称的行。

The exact form of what you want is impossible, as far as I know. As Neil said, names are for us mere humans; the compiler deals with the values.

That said, you can make a utility for giving names to enums. Here's an example:

#define ENUM_NAMES_BEGIN(pType) \
    std::ostream& operator<<(std::ostream& pStream, pType pValue) \
            { \
                switch (pValue) \
                {

#define ENUM_NAMES_CASE_NAMED(pValue, pName) \
                case (pValue): \
                    pStream << (pName); \
                    break;

#define ENUM_NAMES_CASE(pValue) ENUM_NAMES_CASE_NAMED(pValue, #pValue)

#define ENUM_NAMES_END(pDefault) \
                default: \
                    pStream << (pDefault); \
                } \
                \
                return pStream; \
            }

You'd use it as such:

#include <iostream>

enum Days
{
    Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
};

enum NotNamed
{
    DontTry, ImNotnamed
};

ENUM_NAMES_BEGIN(Days)
    ENUM_NAMES_CASE(Sunday)
    ENUM_NAMES_CASE(Monday)
    ENUM_NAMES_CASE(Tuesday)
    ENUM_NAMES_CASE(Wednesday)
    ENUM_NAMES_CASE(Thursday)
    ENUM_NAMES_CASE(Friday)
    ENUM_NAMES_CASE_NAMED(Saturday, "Saturday: Fun day!")
ENUM_NAMES_END("")

int main()
{
    Days d = Saturday; // or whatever
    NotNamed n = ImNotnamed;

    std::cout << "Day: " << d << std::endl;
    std::cout << "Not Named: " << n << std::endl;
}

Trying it with a type that is "unnamed" returns its numeric value.

Note, there isn't actually any enforcement of an enum here; you could use this to name integer values, for example. If you did, operator<< would be ambiguous.

If you can use Boost, use their type trait is_enum (which is fairly complex) and static assert that it be the case. For that the change would be:

#include <boost/static_assert.hpp>
#include <boost/type_traits/is_enum.hpp>

#define ENUM_NAMES_BEGIN(pType) \
    std::ostream& operator<<(std::ostream& pStream, pType pValue) \
            { \
                BOOST_STATIC_ASSERT(boost::is_enum<pType>::value); \
                switch (pValue) \
                {

Now if the type is not an enum, the compile-error at least point to the line where you're trying to define the enum names.

痴梦一场 2024-09-03 18:38:18

(不,这并不能回答一般情况的问题,但某些人可能仍然感兴趣)

正如尼尔在这个问题的评论中所说,你不能在枚举的一般情况。但是,对于个别情况,您可以为枚举类型重载流插入运算符 (<<):

#include <iostream>

enum day_of_week
{
    friday,
    saturday,
    sunday
};

std::ostream& operator<<(std::ostream& o, day_of_week day)
{
    switch (day)
    {
    case friday:   o << "Friday";   break;
    case saturday: o << "Saturday"; break;
    case sunday:   o << "Sunday";   break;
    }
    return o;
}

例如,使用上面的代码, this:

std::cout << saturday << std::endl;

将打印:

Saturday

(no, this doesn't answer the question for the general case, but it might still be of interest to somebody)

As Neil says in the comments to this question, you can't do this in the general case for enumerations. However, for individual cases, you can overload the stream insertion operator (<<) for an enumerated type:

#include <iostream>

enum day_of_week
{
    friday,
    saturday,
    sunday
};

std::ostream& operator<<(std::ostream& o, day_of_week day)
{
    switch (day)
    {
    case friday:   o << "Friday";   break;
    case saturday: o << "Saturday"; break;
    case sunday:   o << "Sunday";   break;
    }
    return o;
}

For example, with the above code, this:

std::cout << saturday << std::endl;

will print:

Saturday
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文