Если я кодирую это
std::map<int, char> example = {
(1, 'a'),
(2, 'b'),
(3, 'c')
};
затем g ++ говорит мне
deducing from brace-enclosed initializer list requires #include <initializer_list>
in C++98 ‘example’ must be initialized by constructor, not by ‘{...}’
и это раздражает меня немного, потому что конструктор является временем выполнения, и может, теоретически перестать работать.
Несомненно, если это сделает, то это перестанет работать быстро и должно делать так последовательно, так, чтобы я должен был быстро определить местоположение и исправить проблему.
Но тем не менее мне любопытно - должен там так или иначе инициализировать карту, вектор, и т.д., во время компиляции?
Править: Я должен был сказать, что разрабатываю для встроенных систем. Не все процессоры будут иметь C++ 0x компилятором. Самое популярное, вероятно, будет, но я не хочу встречаться с глюком и иметь для поддержания 2 версий кода.
Для Повышения я не уверен. Они слабы на использовании их классов Конечного автомата во встроенных системах, так, чтобы был на самом деле, что я кодирую здесь, классы Event/State/Fsm.
Вздох, я предполагаю, что лучше просто избежал бы рискованных действий, но я надеюсь, что это обсуждение было полезно для других.
не в C ++ 98. C ++ 11 поддерживает это, поэтому, если вы включите флаги C ++ 11 и включите то, что предлагает G ++, вы можете.
Редактировать: от GCC 5 C ++ 11 включен по умолчанию
Вы можете использовать BOOST.ASSIGN Библиотека:
#include <boost/assign.hpp>
#include <map>
int main()
{
std::map<int, char> example =
boost::assign::map_list_of(1, 'a') (2, 'b') (3, 'c');
}
Однако, как иил и другие, указанные в приведенных ниже комментариях, эта инициализация происходит во время выполнения, аналогично предложению неблагодаря.
Это не совсем статическая инициализация, но все же, попробуйте. Если ваш компилятор не поддерживает C ++ 0x, я бы пошел на STD :: Map's итерационно-итерационный конструктор :
std::pair<int, std::string> map_data[] = {
std::make_pair(1, "a"),
std::make_pair(2, "b"),
std::make_pair(3, "c")
};
std::map<int, std::string> my_map(map_data,
map_data + sizeof map_data / sizeof map_data[0]);
Это довольно читаемое, не требует никаких дополнительных библиотек и должно работать во всех компиляторы.
С C ++ 0x, возможно, вам может потребоваться использовать брекеты (используйте синтаксис нового стиля для каждой пары):
std::map<int, char> example = { {1,'a'}, {2, 'b'}, {3, 'c'} };
Эти скобки для построения пар не имеют смысла. В качестве альтернативы вы можете полностью назвать каждую пару или использовать make_pair (как вы сделали в C ++ 98)
std::map<int, char> example = {
std::make_pair(1,'a'),
std::make_pair(2, 'b'),
std::make_pair(3, 'c')
};
, что и для создания этих экземпляров при компиляции времени: нет. Контейнеры STL Все инкапсулируют полностью управление временем выполнения.
Я полагаю, вам действительно у вас только есть карта времени компиляции с библиотеками, такими как MetaProgramming Boost's MetaProgramm (не уверена, что не на 100%, если оно совсем правильно, и не изучалось, что это может быть хорошо для):
using namespace boost::mpl;
map<
pair<integral_c<int, 1>, integral_c<char, 'a'> >,
pair<integral_c<int, 2>, integral_c<char, 'b'> >,
pair<integral_c<int, 3>, integral_c<char, 'c'> >
> compile_time_map;
Есть трюк, который вы можете использовать, но только если эти данные не будут использоваться в каком-либо другом статическом конструкторе. Сначала определите простой класс, подобный это:
typedef void (*VoidFunc)();
class Initializer
{
public:
Initializer(const VoidFunc& pF)
{
pF();
}
};
, затем используйте это так:
std::map<std::string, int> numbers;
void __initNumsFunc()
{
numbers["one"] = 1;
numbers["two"] = 2;
numbers["three"] = 3;
}
Initializer __initNums(&__initNumsFunc);
Конечно, это немного перенапряжение, поэтому я бы порекомендовал использовать его только в том случае, если вы действительно должны быть.
С предC++ 0x, самая близкая вещь, которую можно получить, не используя контейнеры, разработанные для использования во время выполнения (и ограничивая себя фундаментальными типами, и агрегируется) :
struct pair { int first; char second; };
pair arr[] = {{1,'a'}, {2,'b'}}; // assuming arr has static storage
к Этому можно было затем получить доступ с помощью некоторого представление карты , или вы могли реализовать обертку, которая допускает совокупную инициализацию, подобную какой Повышение. Массив делает.
, Конечно, вопрос состоит в том, выравнивают ли по ширине преимущества время, помещенное в реализацию этого.
, Если мое чтение корректно здесь, C++ 0x списки инициализатора может давать вам статическую инициализацию неагрегатов как станд.:: станд. карты
и :: пара
, но только если это не изменяет семантику по сравнению с динамической инициализацией.
Таким образом это кажется мне , можно только получить то, что вы попросили то, если ваша реализация может проверить через статический анализ, что поведение не изменяется, если карта
статически инициализируется, но никакие гарантии, что это происходит.
Нет стандартного способа инициализации STD :: Map
во время компиляции. Как упомянутые другие, C ++ 0x позволит компилятору оптимизировать инициализацию, чтобы быть статичным, если это возможно, но это никогда не будет гарантировано.
Помните, однако, что STL - это просто спецификация интерфейса. Вы можете создавать свои собственные совместимые контейнеры и предоставить им статические возможности инициализации.
В зависимости от того, планируете ли вы обновить вашу реализацию Compiler и STL (особенно на встроенной платформе), вы можете даже просто копать в реализации, которую вы используете, добавляете полученные классы и используете их!