перечислимо-международный кастинг: оператор или функция

Это потому, что вы импортируете c_data в init .py, это делает рекурсивный импорт. Чтобы быть более понятным, вы импортируете c_data и определяете flask_app внутри __init__, но позже c_data вы импортируете [ 115], который еще не определен.

from webapp import c_data # Remove it, it makes recursive import

# Place where webapp is defined
flask_app = Flask(__name__)


Попробуйте удалить его. Или измените способ импорта c_data.

Возможное решение, измените run_app.py Не забудьте удалить from webapp import c_data в __init__.py


from webapp import flask_app
from webapp import c_data  # New import

if __name__ == '__main__':
    # Running webapp in debug mode
    flask_app.run(debug=True)
8
задан Jason Plank 1 November 2011 в 20:29
поделиться

5 ответов

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

template<typename T>
T my_enum_convert(int);

template<>
En my_enum_convert<En>(int in) {
    switch(in) {
        case ValA: return VALUE_A;
        case ValB: return VALUE_B;
        case ValC: return VALUE_C;
        default: throw std::logic_error(__FILE__ ": enum En out of range");
    }
}

int my_enum_convert(En in) {
    switch(in) {
        case VALUE_A: return ValA;
        case VALUE_B: return ValB;
        case VALUE_C: return ValC;
        // no default, so that GCC will warn us if we've forgotten a case
    }
}

En enumValue = my_enum_convert<En>(ValA);
int hashDefineValue = my_enum_convert(VALUE_A);
enumValue = my_enum_convert<En>(0); // throws exception

Или что-то как этот - могло бы скорректировать его, если проблемы возникают при использовании его.

Причина я не использовал бы неявное преобразование, состоит в том, что уже существует неявное преобразование от En до интервала, который дает неправильный ответ. Даже если можно надежно заменить это чем-то, что дает правильный ответ, получающийся код не посмотрит, как будто он делает любое преобразование. IMO это препятствует любому, который более поздние взгляды на код больше, чем ввод вызова к подпрограмме преобразования препятствуют Вам.

Если Вы хотите преобразовать в интервал и преобразовать из интервала для взгляда очень отличающимися, то Вы могли дать шаблон и функцию выше различных имен.

С другой стороны, если Вы хотите, чтобы они выглядели одинаково (и больше как static_cast), Вы могли бы сделать:

template<typename T>
T my_enum_convert(En in) {
    switch(in) {
        case VALUE_A: return ValA;
        case VALUE_B: return ValB;
        case VALUE_C: return ValC;
    }
}

int hashDefineValue = my_enum_convert<int>(VALUE_A);

Как записано, T должен иметь неявное преобразование из интервала. Если Вы хотите поддерживать T, который только имеет явное преобразование, используйте "возврат T (ValA)"; вместо этого (или "возврат static_cast <T> (ValA)"; если Вы полагаете, что конструкторы единственного аргумента являются составами исполнителей C-стиля и следовательно непозволительный).

11
ответ дан 5 December 2019 в 12:14
поделиться

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

Если создание класса для этого не является опцией по любой причине, я пошел бы для функций перевода как удобочитаемость во время обслуживания, более важно, чем удобство при написании кода.

2
ответ дан 5 December 2019 в 12:14
поделиться

Вы не можете перегрузить операторы для перечислений. Или я пропускаю что-то? Ну, Вы могли создать своего рода фиктивные классы, которые будут иметь неявного конструктора, берущего интервал, и затем иметь оператор броска к перечислению (и наоборот).

Так, единственное решение состоит в том, чтобы иметь функции. Кроме того, я сделал бы перегрузки, как Patrick предполагает.

1
ответ дан 5 December 2019 в 12:14
поделиться

Функции имеют и затем перегружают библиотечные функции?

//libFunc( enum a );

libFuncOverload( define a ) {
    libFunc( toEn( a ) );
}
1
ответ дан 5 December 2019 в 12:14
поделиться

Преобразование перечисления к интервалу, например, интервала (VALUE_A), происходит автоматически/прозрачно.

Преобразование интервала к перечислению, например, En(ValA), может извлечь выгоду из проверки исправности, чтобы удостовериться, что международное значение является допустимым членом перечисления. (Хотя, надо надеяться, код библиотеки не предполагает, что его перечислимые значения допустимы во-первых.)

В то время как это не поможет с "интервалом x" случаи, можно помочь несколько путем изменения:

#define ValA 5

Кому:

#define ValA VALUE_A

Если перечислимый En () включается/определяется везде, и ValA и VALUE_A будут работать и на нечто (интервал) и на панель (En) везде автоматически/прозрачно.

Вы могли использовать:

#ifdef ValA
STATIC_ASSERT( ValA == VALUE_A, ValA_equal_VALUE_A );
#undef ValA
#else
#warning "ValA undefined.  Defining as VALUE_A"
#endif
#define ValA VALUE_A

Где STATIC_ASSERT - что-то как:

    /* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4(      a,b,c,d)  CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_AGAIN(a,b,c,d)  a ## b ## c ## d

    /* Creates a typedef that's legal/illegal depending on EXPRESSION.       *
     * Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*".              *
     * (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT)                     \
  typedef char CONCATENATE_4( static_assert____,      IDENTIFIER_TEXT,  \
                              ____failed_at_line____, __LINE__ )        \
            [ (EXPRESSION) ? 1 : -1 ]
-1
ответ дан 5 December 2019 в 12:14
поделиться
Другие вопросы по тегам:

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