Можно ли реализовать контейнер типа std :: array (тонкая оболочка вокруг встроенного массива C) с C ++ 0x initializer_list?
Да , ну, пока вы готовы обманывать. Как отмечает Mooing Duck, нет, даже не обманывать, , если разработчики компилятора не позволят вам . Тем не менее, все еще возможно подойти достаточно близко - можно использовать списки инициализаторов и статический массив, который скрыт оболочкой.
Это некоторый код, который я написал для моей личной панели инструментов. Ключ должен полностью игнорировать размер, даже для массива, и позволить контейнеру провайдера обрабатывать его; в этом случае, initializer_list
, который может предоставить размер через std::distance
, таким образом избегая экспликации размера на стороне клиента (кажется, термин, который я только что изобрел).
Поскольку это код типа «любой мог придумать это», нет проблем с его предоставлением «обратно» для публики; На самом деле, я получил идею от какого-то опытного парня, чей ник я не помню на канале Freenode ##c++
, так что, я думаю, признание для них:
* EDIT * изд:
template <typename T> struct carray {
// typedefs for iterator. The best seems to be to use std::iterator<std::random_iterator_tag,T,int> here
...
template <size_t N>
explicit carray (T (&arr)[N])
: ax(arr), sx(N) {}
// note the linked article.
// This works *only* if the compiler implementor lets you.
carray (std::initializer_list<T> X)
: ax (X.begin()), sx(std::distance(X.begin(),X.end()) {}
// YMMV about the rest of the "rule of N":
// no copy constructor needed -- trivial
// no destructor needed -- data outscopes the wrapper
// no assignment operator needed -- trivial
// container functions, like begin(), end(), size()...
private:
T* ax;
size_t const sx;
};
Использование и объявление в режиме C ++ 0x довольно просто (только что протестировано с GCC 4.6 в Fedora 15), но оно работает с предостережениями, отмеченными во внешних ссылках выше, так что это явно неопределенное поведение:
using lpp::carray;
carray<short const> CS = {1, -7, 4, 188};
Однако я не вижу , почему разработчик компилятора не реализовал бы initializer_list интегралов как статический массив в любом случае. Ваш звонок.
Мало того, что он работает таким образом, при условии, что вы можете #ifdef
создать конструктор инициализатора в обычном режиме до C ++ 0x, вы можете использовать его в pre-C ++ 0x; хотя предварительное объявление массива данных в качестве его собственной переменной потребуется, IMHO, оно ближе всего к первоначальному намерению (и оно имеет преимущество в том, что его можно использовать, а не вызывать, например, проблемы с областью видимости). (также протестировано с помощью вышеуказанного компилятора плюс GCC Debian Wheezy):
using lpp::carray;
short data[]= {1, -7, 4, 188};
carray<short const> CS (data);
Там! Нет параметра "size" в любом месте !
Мы также хотели бы предоставить конструктор для указания размера, если список инициализатора не был предоставлен.
Извините, это одна функция, которую я не реализовал. Проблема в том, как назначить память «статически» из внешнего источника, возможно, из Allocator. Если предположить, что это можно сделать как-нибудь через вспомогательный функтор allocate
, тогда конструктор будет выглядеть примерно так:
explicit carray (size_t N)
: ax(allocate(N)), sx(N) {}
Надеюсь, этот код поможет, так как я вижу вопрос более или менее старый.