1>.\SS.cpp(27) : fatal error C1001: An internal error has occurred in the compiler.
1>(compiler file 'msc1.cpp', line 1392)
1> To work around this problem, try simplifying or changing the program near the locations listed above.
1>Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
1> .\SS.cpp(27) : see reference to class template instantiation 'X2IT<x,i>' being compiled
1> with
1> [
1> x=EL3,
1> i=-492
1> ]
1> .\SS.cpp(27) : see reference to class template instantiation 'X2IT<x,i>' being compiled
1> with
1> [
1> x=EL3,
1> i=-491
1> ]
1> .... и так далее
т.е. компилятор пытается раскрыть всё глубже и глубже template. Как его остановить ?
А скорее всего, постарался бы обойтись вообще только трансляцией в RT.
Например так.
1) Завести enum без указания констант
2) Завести функцию, осуществляющую трансляцию в константы и обратно, например по статической таблице...
3) Пользоваться и радоваться...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, dalen, Вы писали:
D>Добрый день!
D>Хочу добиться статического преобразования enum в порядковый номер элемента в этом самом enum.
про две ошибки в коде уже написали,
но есть вопрос — enum это просто асоциация целой константы с именем, грубо говоря
твой енум заменяет несколько макросов
#define EL1 134
#define EL2 10
#define EL3 487
и убирает проблемы свяаные с ними проблемы
А вот что означает "порядковый номер элемента в энуме"? какая-то странная концепция, enum это не упорядоченная структура, просто имя для целочисленной константы, что тогда понимать под номером элемента?
Здравствуйте, Erop, Вы писали:
E>Хотя я не понимаю в чём практический смысл этих упражнений в остроумии? Не пояснишь? E>А скорее всего, постарался бы обойтись вообще только трансляцией в RT. E>Например так. E>1) Завести enum без указания констант E>2) Завести функцию, осуществляющую трансляцию в константы и обратно, например по статической таблице... E>3) Пользоваться и радоваться...
Я сделал по второму методу. Проблема в том, что а) в enum нужны константы, б) нужно связать конкретную константу и некоторые результаты.
Понятно, что можно написать map<Foo::X, pair<double,bool>> но тогда получится лишний overhead на поиск по map. Т.е. смысл такой — есть числовые константы (от 0 до 599), которые не поменять — внешняя библиотека, которая по этим константам считает некоторые данные. Нужно а) рассчитать, б) многократно пробегать по рассчитанным значениям в определенном порядке (не по возрастанию, к сожалению). Соответственно, функции трансляции int -> enum -> int вызываются многократно, при этом 90% вызовов — фактически, указание верхней границы индекса для цикла for(int i = 0; i != X2I(Foo::EL3); i++).
Вот и думаю, можно ли их статически закомпилировать?..
... D>Я сделал по второму методу. Проблема в том, что а) в enum нужны константы, б) нужно связать конкретную константу и некоторые результаты. D>Понятно, что можно написать map<Foo::X, pair<double,bool>> но тогда получится лишний overhead на поиск по map. Т.е. смысл такой — есть числовые константы (от 0 до 599), которые не поменять — внешняя библиотека, которая по этим константам считает некоторые данные. Нужно а) рассчитать, б) многократно пробегать по рассчитанным значениям в определенном порядке (не по возрастанию, к сожалению). Соответственно, функции трансляции int -> enum -> int вызываются многократно, при этом 90% вызовов — фактически, указание верхней границы индекса для цикла for(int i = 0; i != X2I(Foo::EL3); i++). D>Вот и думаю, можно ли их статически закомпилировать?..
Есть решние на половину статическое, наполовину RT. Как-то так:
завести два массива:
int enum2idx[600]; // enum -> idxint idx2enum[600]; // int -> enum
остается только проблема заполнения массивов. Решается написанием простецкого кодогенератора, например используя sed. На вход он получает исходник, с объявлением
class Foo {
public:
enum X {
EL1 = 134,
EL2 = 10,
EL3 = 487
};
};
Здравствуйте, dalen, Вы писали:
D>Хочу добиться статического преобразования enum в порядковый номер элемента в этом самом enum.
Во-первых, согласен с cencio, что перечисления — неупорядоченные множества и говорить о порядковом номере элемента бессмысленно;
Во-вторых, как следствие из "во-первых", привязку значений к порядковым номерам можно только определить самому;
В-третьих, а как быть с повторяющимися значениями в перечислении?
В-четвертых, вариант решения, с учетом сказанного выше:
Здравствуйте, dalen, Вы писали:
D>Вот и думаю, можно ли их статически закомпилировать?..
Ну я бы завёл такой примерно класс:
struct MyEnum {
enum Type {
VBegin = 0,
VEnd = 3
};
static LibEnum GetValue( Type t ) { assert( VBegin <= t && t < VEnd ); return values[t]; }
private:
static const LibEnum values[VEnd];
};
// В *.cppconst LibEnum MyEnum::values[VEnd] = { LibEnum_V1, LibEnum_V2, LibEnum_V3 };
И в своём коде всегда бы работал с MyEnum::Type (или int), MyEnum::VStart, MyEnum::VEnd
Если очень надо, можно ещё и искалку MyEnum по LibEnum написать. Типа std::find заюзать, или цикл написать.
Тогда ещё можно будет и константы типа MyEnum::Type описать. Короче как-то так получается:
// Библиотечный хедерenum LibEnum {
Ups = 100,
Oh = 204,
Waw = -176
};
// твой хедерstruct MyEnum {
enum Type { VBegin = 0, VEnd = 3 };
static const Type Ups;
static const Type Oh;
static const Type Waw;
static LibEnum GetValue( int t ) { assert( VBegin <= t && t < VEnd ); return values[t]; }
static Type FindValue( LibEnum e )
{
for( int i = VBegin; i < VEnd; i++ )
if( values[i] == e )
return static_cast<Type>( i );
return VEnd;
}
private:
static const LibEnum values[VEnd];
};
// твой cpp#define DEC_ENTRY( name ) const MyEnum::Type MyEnum::name = MyEnum::FindValue( ::name );
DEC_ENTRY( Ups )
DEC_ENTRY( Oh )
DEC_ENTRY( Waw )
const LibEnum MyEnum::values[MyEnum::VEnd] = { ::Ups, ::Oh, ::Waw };
// Где-то в кодеvoid foo()
{
const MyEnum::Type skipIt = MyEnum::Waw;
for( int i = MyEnum::VBegin; i < MyEnum::VEnd; i++ ) {
if( i == skipIt )
continue;
CallLibrary( MyEnum::GetValue( i ) ); // Собственно вызов сторонней функции...
}
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском