- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
template <typename T>
struct canref {
struct yes { uint8_t bytes[1]; };
struct no { uint8_t bytes[2]; };
template <typename U> static yes test(U*p);
template <typename U> static no test(...);
static const bool value = sizeof(test<T>(NULL)) == sizeof(yes);
};
template <typename T, int N, bool CanRef=canref<T>::value>
class array;
// class for all types
template <typename T, int N>
class array <T,N,true>
{
struct Bytes
{
uint8_t bytes[sizeof(T)];
};
struct TStruct
{
T t;
TStruct(T t):t(t){}
};
Bytes elements[N];
int count;
void copy_ctor (int index, const T& t)
{
new (&((*this)[index])) T(t);
}
void copy (int index, const T& t)
{
(*this)[index] = t;
}
void dtor (int index)
{
(*this)[index].~T();
}
public:
array () : count(0) {}
~array ()
{
resize(0);
}
T& operator [] (int index)
{
assert (index>=0 && index<count);
return ((TStruct*)(&elements[index]))->t;
}
const T& operator [] (int index) const
{
assert (index>=0 && index<count);
return ((TStruct*)(&elements[index]))->t;
}
template <int M>
array (const array<T,M> &a)
{
assert(a.count<=N);
count = a.count;
for (int i=0; i<count; ++i)
copyctor(i, a[i]);
}
template <int M>
array& operator = (const array<T,M> &a)
{
if (this != &a)
{
if (count>a.count)
{
for (int i=0; i<a.count; ++i) copy(i, a[i]);
for (int i=a.count; i<count; ++i) dtor(i);
count = a.count;
} else
{
assert(a.count<=N);
int ocount = count;
count = a.count;
for (int i=0; i<ocount; ++i) copy(i, a[i]);
for (int i=ocount; i<count; ++i) copy_ctor(i, a[i]);
}
}
}
int size()
{
return count;
}
guest 10.01.2014 13:49 # 0
bormand 10.01.2014 13:59 # −1
guest 10.01.2014 15:01 # +2
bormand 10.01.2014 15:41 # +5
kegdan 10.01.2014 16:13 # +2
Мистер Хэнки 12.01.2014 22:32 # 0
LispGovno 12.01.2014 23:02 # −1
3.14159265 12.01.2014 23:07 # 0
Lure Of Chaos 12.01.2014 23:22 # +1
eth0 13.01.2014 21:31 # 0
Я тут как-то днесь код читал для 7.7, написанный человеком, не могущим в "алгоритмы". Если бы не сила воли, я бы лоб себе разбил фейспальмами.
kegdan 13.01.2014 21:37 # 0
после него 1с - мана небесная
Abbath 13.01.2014 00:09 # 0
kegdan 13.01.2014 06:31 # +2
TarasB 10.01.2014 16:29 # 0
roman-kashitsyn 10.01.2014 16:40 # +1
TarasB 10.01.2014 16:42 # 0
roman-kashitsyn 10.01.2014 16:46 # 0
guest 10.01.2014 17:05 # 0
[color]LispGovno[/color]
LispGovno 10.01.2014 18:46 # 0
LispGovno 10.01.2014 18:50 # 0
class raw_storage_iterator
чтобе передать в OutputIt не указатель, а например другой итератор?
bormand 10.01.2014 18:52 # 0
Может быть вот так его юзают?
LispGovno 10.01.2014 19:00 # 0
Ну как то так.
Это приведет к вызову конструктора копирования в неинициализированные области памяти.
bormand 10.01.2014 19:07 # 0
LispGovno 10.01.2014 19:15 # 0
(компилировать не пробовал, но все логично)
TarasB 10.01.2014 17:19 # −1
LispGovno 10.01.2014 18:48 # 0
Ты пишешь игру в сто строк? Тогда тебе перевод каретки нужно вставлять реже.
bormand 10.01.2014 18:53 # +1
Самое сложное - инклуды. А остальное и в одну войдет.
3Doomer 13.01.2014 07:25 # +1
kegdan 13.01.2014 07:45 # +1
bormand 10.01.2014 15:13 # +3
- в конструкторе передать нельзя
- скобки крашатся, если index >= count, а он всегда равен 0
- конструктор копий и присваивание требуют другой такой же массив
Вещь в себе какая-то ;(
guest 10.01.2014 15:31 # +1
TarasB 10.01.2014 16:26 # +2
push_back
он не влез в 100 строк
а ещё там вторая реализация класса для случая, когда третий параметр false
TarasB 10.01.2014 16:26 # +2
УУУУУИИИИИХХХХААААААААА!!!!
Моё шаблонное говно выложил не я, а другой человек.
3.14159265 12.01.2014 23:25 # +2
defecate-plusplus 12.01.2014 23:33 # +6
Ваш индекс научного цитирования увеличился вдвое.
roman-kashitsyn 10.01.2014 17:03 # +3
TarasB 10.01.2014 17:20 # 0
Верхняя сама смещается в push_back
Ещё есть resize, который умеет только уменьшать, иначе надо чем-то заполнять добавленный хвост, а чем, ведь мой класс не требует пустого конструктора от T.
roman-kashitsyn 10.01.2014 17:33 # 0
Тарас, объясни, зачем нужен TStruct?
TarasB 10.01.2014 17:39 # 0
Сейчас он не нужен.
Что такое паддинг? Если чё, я специально спрашивал, смещение первого поля в структурах всегда нулевое.
guest 10.01.2014 17:50 # +4
TForm1
roman-kashitsyn 10.01.2014 17:50 # 0
Но вариант с char raw_memory[sizeof(T) * N]; внутри array мне нравится гораздо больше.
TarasB 10.01.2014 17:58 # 0
Ну возьму я указатель на последний элемент, приведу его к TStruct (содержимое вылазит за, но мы к нему не обращаемся же!), возвращаем лишь ссылку на t, которое никуда не вылазит.
> Но вариант с char raw_memory[sizeof(T) * N]; внутри array мне нравится гораздо больше.
Тут всё ради того, чтобы уйти от этого.
А если размер - миллион? Идея как раз в том, чтобы охрененно большой массив не содержал переголовы на инициализацию, и при этом не "содержал" неинициализированных полей.
LispGovno 10.01.2014 18:55 # +1
> переголовы на инициализацию
Не будет он инициализироваться. Ча содержит тривиальный конструктор. То есть пустой и он не будет вызываться.
TarasB 10.01.2014 18:59 # 0
Так тоже можно, но мне показалось, что проще Bytes[N], не надо руками умножать для получения адреса, пусть компилятор умножает.
roman-kashitsyn 10.01.2014 19:36 # +1
reinterpret_cast
bormand 10.01.2014 19:41 # 0
Вроде же только в сторону char * можно кастовать.
P.S. Хотя, с другой стороны, сторону с char* никто никогда не юзает, поэтому никаких проблем с алиасингом быть не должно.
roman-kashitsyn 10.01.2014 19:48 # 0
bormand 10.01.2014 19:54 # 0
http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
LispGovno 10.01.2014 20:06 # 0
bormand 10.01.2014 20:24 # +2
А нельзя вроде бы куда угодно, даже через char.
Если я правильно понял, компилятор не трекает кого там в кого копировали. А просто смотрит по прстоым правилам, приведенным в стандарте:
- один из типов чар - может наехать
- типы одинаковые - может наехать
- типы одного размера - может наехать
...
и т.п.
И исходя из этого задумывается, можно ли ему читать вот этот int *p, или сначала надо положить вон в тот int *q, который был написан пару строчек назад, а не откладывать запись в *q после записи в *p.
Поэтому каст через промежуточный чар будет иметь тот же самый эффект, что и каст напрямую. Ну если я не туплю.
LispGovno 10.01.2014 20:28 # 0
bormand 10.01.2014 20:28 # +1
LispGovno 10.01.2014 20:38 # 0
тупо вместо:
буду писать
Или даже так:
bormand 10.01.2014 20:40 # 0
А зачем вообще так делать?
b = (int32_t)a или b = static_cast<int32_t>(a) уже не возбуждают?
LispGovno 10.01.2014 20:49 # 0
LispGovno 10.01.2014 20:53 # +1
bormand 10.01.2014 21:02 # +1
Ага. Железобетонно. Плюёт на проблемы индейцев. И, кстати говоря, всяко лучше оптимизируется. Т.к. нету лишних прокруток через память, и data flow не порушено. Может быть даже сдвигов не будет, если например int64_t был получен умножением. Или "повезет" (а вернее постараяется компилер), и куски int64_t окажутся в нужных регистрах на 32 битной архитектуре.
bormand 10.01.2014 20:44 # +3
> int32_t b = 5;
> std::memcpy(a, &b, sizeof(b));
Кстати говно, от индейцев зависит. При больших индейцах скопирует в старшую часть, а при маленьких - в младшую. Впрочем изначальный код так же "работал".
LispGovno 10.01.2014 20:41 # 0
bormand 10.01.2014 20:42 # +1
Да хрен бы знал. Я тоже кучу раз нарушал. Но в gcc не баговало ;)
TarasB 11.01.2014 11:07 # +1
bormand 11.01.2014 11:26 # 0
Часто есть, но он далеко не всегда может предупредить. Т.к. если бы он всегда понимал ситуацию - он бы точно знал, когда можно, а когда нет, и проблемы бы просто не существовало.
В идеале - лучше всего вообще не держать разнотипных указателей на одну и ту же локацию в памяти. Ибо не только на алиасинг, но и на выравнивания и на индейцев нарваться можно. Да оно и не особо нужно.
Если приведешь примеры, где тебе понадобились разнотипные указатели на одну локацию - попробуем разобраться.
Xom94ok 10.01.2014 21:51 # +2
> интересуют студии 2008 и много младше
7.1 закрывает на это глаза. Шестая чуть ли не просит: "нарушь стрикт алиасинг, пожалуйста, я прошу тебя..."
bormand 10.01.2014 21:52 # +3
Каким образом? :)
Xom94ok 10.01.2014 22:06 # +2
Примерно так же, как одиноко идущая ночью нетрезвая девушка, одетая в минимум одежды, неявно, всем своим видом просит любви, нежности, ласки...
LispGovno 10.01.2014 22:09 # +3
LispGovno 10.01.2014 22:00 # +3
Ох она какая проказница... Её нужно наказать.
bormand 10.01.2014 20:32 # 0
Компилятор: "я писал в этот char *, а теперь мне нужно прочитать тот int *, но они могут ссылаться на одно и то же место, поэтому мне нельзя передвигать запись в char* на потом, за чтение int *, или вообще выкидывать ее".
Или все-таки я туплю?
bormand 10.01.2014 20:38 # +1
The converse is not true. Casting a char* to a pointer of any type other than a char* and dereferencing it is usually in volation of the strict aliasing rule.
Не могу понять, откуда она выводится.
bormand 10.01.2014 20:49 # 0
Вот она как раз и падает. И char * походу там вообще не при делах, и всетаки алиасится с чем угодно... Просто в данном примере char в операциях чтения\записи не участвовал, а участвовали uint32_t и uint16_t, о алиасинге которых компилятор не подумал.
Поэтому предположение остается: направление каста ни на что не влияет. Главное - в какие локации памяти я пишу, и из каких читаю.
LispGovno 10.01.2014 20:58 # 0
bormand 10.01.2014 21:00 # 0
Можно кастить что угодно куда угодно, и в любом порядке, если я все правильно понял. Сам каст абсолютно ни на что не влияет, т.к. компилятор не трекает их.
LispGovno 10.01.2014 21:04 # 0
bormand 10.01.2014 21:10 # 0
Ты мог сами указатели (не то, на что они ссылаются, а сами указатели) через memcpy скопировать вместо каста и получить ту ж самую хуйню.
Ты мог передать их другой функции, и получить ту же самую хуйню.
Ты мог получить в аргументах 2 указателя разного типа, но ссылающихся на одну и ту же хуйню.
Во всех случаях будет такая бага. Хотя каста, как такового, рядом вообще нет.
LispGovno 10.01.2014 21:01 # 0
bormand 10.01.2014 21:05 # 0
Не, вот на это там примера вроде как и нет.
В примере к этой фразе писали в int16_t*, а читали из заалиасенного с ним int32_t. char* там вообще сбоку валялся, для красоты.
Это пример как раз на твой случай: "а давайте наебем компилятор, и кастанем не напрямую, а через char *"
LispGovno 10.01.2014 22:50 # +1
TarasB 11.01.2014 11:08 # 0
LispGovno 11.01.2014 11:28 # 0
Если тебя интересует нарушение строго аналисинга, то UB с его участием в приведенном фрагменте нет.
TarasB 11.01.2014 11:31 # 0
Правда у меня не char*, а uint8_t*, но вроде бы разница не принципиальна.
А УБ с паддингом?
LispGovno 11.01.2014 11:57 # 0
bormand 11.01.2014 11:59 # 0
Ну здесь T лежит в TStruct, а char[sizeof(T)] лежит в Bytes. И если компилятор что-то будет дописывать (а в конец структур, емнип, выравнивание не добавляется, только между полей), то допишет он это к обеим структурам.
TarasB 11.01.2014 12:02 # 0
LispGovno 11.01.2014 12:05 # 0
TarasB 11.01.2014 12:11 # 0
LispGovno 11.01.2014 12:13 # 0
roman-kashitsyn 11.01.2014 12:53 # 0
Не может, т.к. имеет нетривиальный конструктор.
LispGovno 11.01.2014 13:56 # 0
TarasB 11.01.2014 14:07 # 0
char [sizeof(T[N])]
LispGovno 10.01.2014 19:46 # 0
Может нельзя? Выравнивание между T может вставить.
bormand 10.01.2014 19:46 # 0
bormand 10.01.2014 19:49 # 0
empty set of N sub-objects of type T.
TarasB 10.01.2014 19:50 # 0
bormand 10.01.2014 19:56 # 0
roman-kashitsyn 10.01.2014 19:50 # 0
Вот тут как раз выравнивания быть не может.
LispGovno 10.01.2014 19:31 # +2
guest 11.01.2014 01:14 # +5
guest 11.01.2014 01:17 # 0
guest 11.01.2014 01:20 # 0
guest 11.01.2014 01:20 # 0
guest 11.01.2014 01:23 # 0
roman-kashitsyn 10.01.2014 21:28 # +1
bormand 10.01.2014 21:32 # +1
+
tiny_buffer(std::size_t n)
=
tiny_buffer(std::size_t n, const value_type & v = value_type())
for (std::size_t i = 0; i < size_; ++i) data()[i].~value_type();
=
shrink(0) // если нам пофиг на лишнее присваивание в size_, но можно и правда вынести оба тела в какой-нибудь unfill.
roman-kashitsyn 11.01.2014 00:21 # 0
LispGovno 11.01.2014 00:26 # −1
No
guest 11.01.2014 01:08 # −1
LispGovno 11.01.2014 01:15 # −1
guest 11.01.2014 01:16 # −1
)))
LispGovno 11.01.2014 11:18 # −1
bormand 11.01.2014 09:25 # −1
TarasB 11.01.2014 11:09 # −1
roman-kashitsyn 11.01.2014 11:13 # +1
Инстанциируются и проходят полную проверку всегда только те члены шаблонов класса, которые реально используются. Если ты не вызываешь член, который требует конструктора по умолчанию, то и ошибки компиляции не будет.
В частности, это применимо к перегруженным функциям: если одна из перегрузок вызывает ошибку компиляции, она просто исключается из рассмотрения, см. "Substitution failure is not an error"
bormand 11.01.2014 12:03 # +1
TarasB 11.01.2014 12:11 # −1
bormand 11.01.2014 12:35 # 0
defecate-plusplus 11.01.2014 12:12 # +2
TarasB 11.01.2014 12:25 # 0
roman-kashitsyn 11.01.2014 12:46 # +1
TarasB 11.01.2014 12:10 # 0
defecate-plusplus 11.01.2014 12:18 # +1
LispGovno 10.01.2014 21:33 # +1
std::unfill
TarasB 13.01.2014 11:29 # +2
LispGovno 10.01.2014 21:34 # −7
LispGovno 10.01.2014 21:34 # −5
LispGovno 10.01.2014 21:35 # −6
LispGovno 10.01.2014 21:37 # −2
LispGovno 10.01.2014 21:43 # −2
Повыше тоже
TarasB 11.01.2014 14:08 # +4
bormand 11.01.2014 15:17 # +8
- спойлеры
- личку
- ссылки
LispGovno 11.01.2014 15:23 # +6
LispGovno 11.01.2014 15:27 # +2
|---------|
|---------|
|---------|
LispGovno 11.01.2014 15:33 # +10
███████
███████
███████
inkanus-gray 13.01.2014 15:39 # 0
govnomonad 11.01.2014 15:27 # +3
RFC2616
roman-kashitsyn 10.01.2014 23:12 # +2
bormand 10.01.2014 21:35 # 0
LispGovno 10.01.2014 21:40 # +1
TarasB 13.01.2014 10:57 # 0
а чё std::destroy нема?
defecate-plusplus 13.01.2014 11:02 # +1
roman-kashitsyn 13.01.2014 11:18 # +3
defecate-plusplus 13.01.2014 11:33 # +1
как лишп говно выше намекнул, к std::uninitialized_fill нужен std::initialized_unfill
roman-kashitsyn 13.01.2014 11:04 # 0
roman-kashitsyn 10.01.2014 23:24 # +2
TarasB 11.01.2014 11:14 # 0
вынести в array<void*, TypeSize, N> это хорошая идея, ибо меньше пустоо дублирования кода, но я до такого колдунства ещё не дорос.
Я слишком ленив, чтобы писать std::move на двести строк.
LispGovno 11.01.2014 11:15 # 0
Чё?
TarasB 11.01.2014 11:30 # 0
на самом деле это больше к вопросу о том, что если язык имеет слишком низкой уровень, то для того, чтобы заставить компилятор правильно себя вести во всех случаях, то надо пиздец как изъебнуться
roman-kashitsyn 11.01.2014 11:39 # +4
TarasB 11.01.2014 11:54 # 0
но вопрос оптимизации под конкретные случаи бесконечен, и если им задрачиваться по полной, то в конце концов ещё и окажется, лол, что без шаблонов кода не больше
roman-kashitsyn 11.01.2014 11:24 # +1
Кто такие сильки? Массивы/вектора ссылок языком запрещены, так можно работать только с указателями.
Насколько я понимаю, теперь уже вообще не нужен CanRef, т.к. общую реализацию для "силек" и значений у тебя сделать не получилось. Вроде бы легко можно обойтись гораздо более прозрачной специализацией шаблонов.
TarasB 11.01.2014 11:30 # 0
да, реализации разные
roman-kashitsyn 11.01.2014 11:35 # +1
Зачем нарушать семантику языка?
TarasB 11.01.2014 11:52 # +3
Я ПОШЁЛ ПРОТИВ СИСТЕМЫ
(первый вариант был более двусмысленный)
bormand 11.01.2014 11:48 # 0
TarasB 11.01.2014 12:12 # +2
TarasB 13.01.2014 11:17 # 0
http://codepaste.ru/16746/
TarasB 13.01.2014 11:36 # 0
LispGovno 13.01.2014 11:41 # +2
codepaste.ru содержит материалы «для взрослых»
В настройках вашей сети запрещён показ страниц с подобных ресурсов.
TarasB 13.01.2014 11:43 # +2
LispGovno 13.01.2014 11:45 # +1
roman-kashitsyn 13.01.2014 12:25 # 0
TarasB 13.01.2014 12:57 # 0
Потому что у меня в коде везде инт, и необходимость каждый раз кастить для индексации, чтобы компилятор не ебал мозг, меня угнетает.
И да, я пиздец как много потеряю от того, что я не смогу завести больше 2млрд элементов.
roman-kashitsyn 13.01.2014 13:09 # 0
> если это единственное замечание
Сейчас пока времени нет нормально ревьюить, знаковость просто первой в глаза бросилась...
TarasB 13.01.2014 13:13 # 0
да только вот гемор с кастами лишний при этом получается
> В частности unsigned избавляет от необходимости проверять положительность индексов/размеров.
В релизе проверок нет, в дебаге пох, к тому же компилятор сам умеет оптимизировать код в одну проверку:
assert ( unsigned(index) < m_size );
LispGovno 13.01.2014 15:07 # 0
TarasB 13.01.2014 15:36 # 0
bormand 13.01.2014 14:01 # +2
Готовится к переходу на жабу.