Строка синтаксического анализа к перечислимому типу

Это действительно не дает объяснение, но здесь - то, что Stroustrup должен сказать об этом в "Выпуске Трети Языка Программирования на C++":

10.4.6.2 членских Констант

также возможно инициализировать статического интегрального постоянного участника путем добавления константное выражение инициализатор к его объявлению элемента. Например:

class Curious {
    static const int c1 = 7;        // ok, but remember definition
    static int c2 = 11;             // error: not const
    const int c3 = 13;              // error: not static
    static const int c4 = f(17);    // error: in-class initializer not constant
    static const float c5 = 7.0;    // error: in-class not integral
    // ...
};

Однако инициализированный участник должен все еще быть (исключительно) определен где-нибудь, и инициализатор не может быть повторен:

const int Curious::c1;  // necessary, but don't repeat initializer here

я считаю это ошибкой. При необходимости в символьной константе в рамках объявления класса используйте перечислитель (4.8, 14.4.6, 15.3). Например:

class X {
    enum { c1 = 7, c2 = 11, c3 = 13, c4 = 17 };
    // ...
};

Таким образом, никакое членское определение не необходимо в другом месте, и Вы не испытываете желание объявить переменные, числа с плавающей запятой, и т.д.

И в Приложении C (Технические особенности) в Разделе C.5 (Константные выражения), Stroustrup говорит следующее о "константных выражениях":

В местах, таких как границы массива (5.2), маркировки случая (6.3.2) и инициализаторы для перечислителей (4.8), C++ требует константное выражение . Константное выражение оценивает к интегралу или постоянному перечислению. Такое выражение состоит из литералов (4.3.1, 4.4.1, 4.5.1), перечислители (4.8), и consts, инициализированный константными выражениями. В шаблоне целочисленный шаблонный параметр может также использоваться (C.13.3). Плавающие литералы (4.5.1) могут использоваться только если явно преобразованный в целочисленный тип. Функции, объекты класса, указатели и ссылки могут использоваться в качестве операндов к оператор (6.2) sizeof только.

Интуитивно, константные выражения являются простыми выражениями, которые могут быть оценены компилятором, прежде чем программа будет связана (9.1) и начнет работать.

Примечание, которое он в значительной степени не учитывает плавающую точку как способность играть в 'константных выражениях'. Я подозреваю, что плавающая точка была упущена из этих типов константных выражений просто, потому что они не достаточно 'просты'.

16
задан Rex M 16 September 2009 в 18:19
поделиться

5 ответов

Что насчет чего-то вроде:

public static class EnumUtils
{
    public static Nullable<T> Parse<T>(string input) where T : struct
    {
        //since we cant do a generic type constraint
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("Generic Type 'T' must be an Enum");
        }
        if (!string.IsNullOrEmpty(input))
        {
            if (Enum.GetNames(typeof(T)).Any(
                  e => e.Trim().ToUpperInvariant() == input.Trim().ToUpperInvariant()))
            {
                return (T)Enum.Parse(typeof(T), input, true);
            }
        }
        return null;
    }
}

Используется как:

MyEnum? value = EnumUtils.Parse<MyEnum>("foo");

(Примечание: использовалась старая версия try / catch около Enum.Parse )

31
ответ дан 30 November 2019 в 15:51
поделиться
private enum MyEnum
{
    Enum1 = 1, Enum2 = 2, Enum3 = 3, Enum4 = 4, Enum5 = 5, Enum6 = 6, 
    Enum7 = 7, Enum8 = 8, Enum9 = 9, Enum10 = 10
}

private static Object ParseEnum<T>(string s)
{
    try
    {
        var o = Enum.Parse(typeof (T), s);
        return (T)o;
    }
    catch(ArgumentException)
    {
        return null;
    }
}

static void Main(string[] args)
{
   Console.WriteLine(ParseEnum<MyEnum>("Enum11"));
   Console.WriteLine(ParseEnum<MyEnum>("Enum1"));
   Console.WriteLine(ParseEnum<MyEnum>("Enum6").GetType());
   Console.WriteLine(ParseEnum<MyEnum>("Enum10"));
}

ВЫХОД:

    //This line is empty as Enum11 is not there and function returns a null
Enum1
TestApp.Program+MyEnum
Enum10
Press any key to continue . . .
5
ответ дан 30 November 2019 в 15:51
поделиться

У меня есть метод TryParseName в UnconstrainedMelody , библиотека для служебных методов делегирования и перечисления, которая использует «невыразимые» ограничения с помощью некоторых уловок после сборки. (Код , использующий , библиотека не требует постбилда, просто для ясности.)

Вы бы использовали его так:

Foo foo;
bool parsed = Enums.TryParseName<Foo>(name, out foo);

В настоящее время у меня нет версии без учета регистра, но Я могу легко представить одного, если хотите. Обратите внимание, что этот не пытается анализировать числа, например, «12», как это делает встроенная версия, и не пытается анализировать списки флагов, разделенных запятыми. Я могу добавить версию flags позже, но я не вижу особого смысла в числовой версии.

Это делается без упаковки и без проверки типа времени выполнения. Наличие ограничения действительно удобно:

2
ответ дан 30 November 2019 в 15:51
поделиться

Я только что объединил синтаксис из здесь с обработкой исключений из здесь , чтобы создать следующее:

public static class Enum<T>
{
    public static T Parse(string value)
    {
        //Null check
        if(value == null) throw new ArgumentNullException("value");
        //Empty string check
        value = value.Trim();
        if(value.Length == 0) throw new ArgumentException("Must specify valid information for parsing in the string", "value");
        //Not enum check
        Type t = typeof(T);
        if(!t.IsEnum) throw new ArgumentException("Type provided must be an Enum", "TEnum");

        return (T)Enum.Parse(typeof(T), value);
    }
}

Вы можете вертеться немного, чтобы вернуть ноль вместо выдачи исключений.

2
ответ дан 30 November 2019 в 15:51
поделиться

Если вы используете .NET 3.5 (или даже 2.0, если вы удалите метод расширения), мне очень повезло с методами, описанными в этой статье:

Перечисления и Строки - Остановите безумие!

РЕДАКТИРОВАТЬ: Домен исчез и теперь представляет собой ферму ссылок. Я вытащил код (слегка измененный и добавленный со временем) из нашей кодовой базы на работе, который теперь вы можете найти здесь:

https://gist.github.com/1305566

2
ответ дан 30 November 2019 в 15:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: