Здравствуйте, x-code, Вы писали:
XC>Что-то эта тема (шаблоны с переменным числом аргументов) как-то вообще мимо меня прошла XC>Вы можете рассказать хоть что-то поподробнее, как оно вообще работает? XC>Как такие шаблоны разворачиваются в компиляторе? XC>Какие есть вообще способы с ними работать?
и тебя в гугле забанили? попробуй тогда какой-нибудь яндекс или поиск мейл.ру
Здравствуйте, Abyx, Вы писали:
A>и тебя в гугле забанили? попробуй тогда какой-нибудь яндекс или поиск мейл.ру
учись у Кодта объяснять а не гнать людей отсюда
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, x-code, Вы писали:
XC>Что-то эта тема (шаблоны с переменным числом аргументов) как-то вообще мимо меня прошла XC>Вы можете рассказать хоть что-то поподробнее, как оно вообще работает? XC>Как такие шаблоны разворачиваются в компиляторе? XC>Какие есть вообще способы с ними работать?
Как разворачиваются: берётся серия аргументов (параметров шаблона, аргументов функции) и подставляется одним махом.
template<bla,bla,bla> struct Foo; // не обязательно вариадик, а просто много-много-арный шаблонvoid foo(bla,bla,bla); // то же самое - там могут быть и дефолтные параметры, и сишный эллипсис,void foo(); // и перегрузки, и что угодноtemplate<class... Args> void bar(Args... args) // если параметры шаблона не указаны, они довыводятся из аргументов
{
Foo<Args...> x; // подставили параметры шаблона - здесь типы - в параметры другого шаблона.
foo(args...); // подставили серию аргументовsizeof...(Args); // число параметров шаблонаsizeof...(args); // число аргументов функцииint xs[] = { f<Args>()... }; // подставили каждый элемент Args в выражение - например, в шаблон функцииvoid* ys[] = { new Args()... }; // необязательно в шаблон - типы можно использовать как угодноint zs[] = { f(args)... }; // подставили каждый элемент args
}
Ну и всякие операции над сериями параметров шаблонов возможны. Например, сопоставление (с началом серии).
В общем, метапрограммирование во всей красе. Раньше был лисп, а теперь чуть-чуть не дотянули до рефала.
template<class... Args> struct mpl_series {};
// можно делать сопоставление глубокоtemplate<class> struct mpl_front;
template<class X, class... Args> struct mpl_front< mpl_series<X,Args...> > { typedef X type; };
// а можно и непосредственноtemplate<class... Args> struct mpl_sizeof;
template<> struct mpl_sizeof<> {
static int const value = 1;
};
template<class X, class... Rest> struct mpl_sizeof<X,Rest...> {
static int const value = 1 + mpl_sizeof<Rest...>::value;
};
// единственно, склеивать две последовательности напрямую не выйдет, хотя бы одна должна быть упакованаtemplate<class Series, class...> struct mpl_append;
template<class... Xs, class... Ys> struct mpl_append< mpl_series<Xs...>, Ys... >
{ typedef mpl_series<Xs...,Ys...> type; };
template<class Series1, class Series2> struct mpl_concat;
template<class... Xs, class... Ys> struct mpl_concat< mpl_series<Xs...>, mpl_series<Ys...> >
{ typedef mpl_series<Xs...,Ys...> type; };
// и, с хвостом серии нельзя напрямую сопоставляться, хвост можно только порождатьtemplate<class Series> struct mpl_rotate;
template<class X, class...Ys> struct mpl_rotate< mpl_series<X,Ys...> >
{ typedef mpl_series<Ys...,X> };
Здравствуйте, Кодт, Вы писали:
К>Да любым способом утилизировать произвольное количество аргументов.
Что-то эта тема (шаблоны с переменным числом аргументов) как-то вообще мимо меня прошла
Вы можете рассказать хоть что-то поподробнее, как оно вообще работает?
Как такие шаблоны разворачиваются в компиляторе?
Какие есть вообще способы с ними работать?
Здравствуйте, x-code, Вы писали:
XC>Похоже на обычные кортежи времени компиляции (tuples) в свойственной С++ извращенной манере XC>И раскрытие этих "пакетов параметров", как я понимаю, только или пакетом (сразу все) или рекурсивно?
Вот в этом-то и услада, что сразу всё, а не рекурсивно, как в былые времена.
Плюс, можно делать вещи, которые на рекурсии в принципе невозможны. Массив создать, например. Или функцию с кучей параметров вызвать.
Не, раньше тоже выкручивались, генерировали достаточное количество перегрузок на все разумные случаи арности.
Но это хорошо, когда у тебя есть буст, а у буста есть соответствующие решения.
А тут без буста можно, сразу.
Здравствуйте, niXman, Вы писали:
X>может быть ты уже хоть раз прочтешь книжку?!
А может ты перестанешь посылать людей читать книжку? Лень отвечать на простой (для тебя) вопрос, пройди мимо. В чем проблема?
Здравствуйте, Lonely Dog, Вы писали:
LD>А в гугле/яндексе как эта информация появилась? Кто-то спросил, ему ответили. Почему нельзя спрашивать здесь?
нет, начала написали пропозалы, потом Струструп написал C++11 FAQ, потом это скопировали в википедию на 100 языках,
а потом набежала толпа ленивых нубов, и они начали задавать вопросы, ответы на которые написаны в википедии/FAQ
Здравствуйте, Lonely Dog, Вы писали:
LD>RSDN ценен контентом, а не ответами в стиле "ищи в гугле". Жаль, что ты этого не понимаешь
понимать это должны те, кто с этого что-то получает
мне, и еще многим, на rsdn просто нас****, ибо выбор огромен
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
XC>В общем, книжки это хорошо, но недостаточно. XC>Вопрос про данную хитрую конструкцию вполне достойный. Я понимаю, если бы спросили как работает оператор if, или, простихосподи, goto. Или просили бы написать лабу в стиле "ввести два числа, вывести сумму двух чисел". Но тут — какая-то хитровывернутая конструкция из малоизвестных, экзотических и только-что появившихся возможностей С++.
О том и речь. У меня тупо нет времени изучать новые возможности C++. Узнаю про них из таких вот постов. Вряд ли буду использовать, но для общего развития интересно.
Здравствуйте, niXman, Вы писали:
X>так вы об этом) X>это нормально, и прописано в стандарте.
Как бы да. Просто сначала появилась версия, что такая форма как-то позволяет специфицировать порядок вызовов. Иначе совсем непонятно — зачем она нужна.
Здравствуйте, Hard_Club, Вы писали:
H_C>Как эта штука — #define CALL(expr) ( (expr), void(), 0 ) — называется в стандарте?
Comma operator
Неявно определён над любыми (в т.ч. void) операндами, строго последовательно выполняет их и возвращает значение правого операнда.
Здесь получается такая конструкция
Первая запятая над expr и void нужна для того, чтобы предотвратить нечаянный выбор перегруженного оператора запятой. (Перегрузить оператор для void-аргумента в принципе невозможно).
Результат имеет тип void, а уже void,int — заведомо — неявно определён компилятором.
Подытоживая,
— f(x) — может быть void или какого-нибудь неудобного для передачи в (...) типа
— f(x),0 — может быть типа с перегруженным operator,(T,int) — получим вместо int неизвестно что
— f(x),void() — получим void, но ничего с ним не сможем сделать
— f(x),void(),0 — получим int
К>Подытоживая, К>- f(x) — может быть void или какого-нибудь неудобного для передачи в (...) типа К>- f(x),0 — может быть типа с перегруженным operator,(T,int) — получим вместо int неизвестно что К>- f(x),void() — получим void, но ничего с ним не сможем сделать К>- f(x),void(),0 — получим int
Здравствуйте, Кодт, Вы писали:
К>Конструктор значения типа void %) К>Ещё встречается чуть менее лаконичное (void)0
void — это какой-то хак в системе типизации, причем явно перегруженный смыслом
с одной стороны, это неполный "тип" и у него не может быть экземляров, а с другой стороны это и не тип вообще
Здравствуйте, niXman, Вы писали:
X>стОит отметить, что выражение типа: X>
X>int v = 0;
X>((void)v);
X>
X>не означает, что v станет типом void. это просто "посыл" компилятору о том, что если v не используется, чтоб он не сообщал об этом.
Как раз означает. Просто у нас не так много возможностей напрямую пообщаться с этим недотипом, не получив ill-formed программу.
Это return в шаблонах и лямбдах с выводом возвращаемого типа, а ещё старый добрый оператор запятая.
На самом деле, с таким же успехом можно любое выражение, содержащее v, написать. Лишь бы побочных эффектов у него не было.
int v = 0;
v; // так
v*0; // или такsizeof(v); // или так
Но компилятор на это может сказать варнинг: "результат выражения никуда не использован".
Для функций делается попущение
template<class T>
int unused(T const&) { return 0; } // мы-то знаем, что эта функция ничего не делаетvoid f() {
int v = 123;
unused(v); // компилятор не расстраивается, что мы не использовали этот 0
printf(""); // ведь здесь мы не использовали результат вычисления printf, а он там есть...
Здравствуйте, Кодт, Вы писали:
К>Как разворачиваются: берётся серия аргументов (параметров шаблона, аргументов функции) и подставляется одним махом.
Похоже на обычные кортежи времени компиляции (tuples) в свойственной С++ извращенной манере
И раскрытие этих "пакетов параметров", как я понимаю, только или пакетом (сразу все) или рекурсивно?
К> int xs[] = { f<Args>()... }; // подставили каждый элемент Args в выражение — например, в шаблон функции
тут получается массив из результатов вызовов
Здравствуйте, Hard_Club, Вы писали:
К>> int xs[] = { f<Args>()... }; // подставили каждый элемент Args в выражение — например, в шаблон функции H_C>тут получается массив из результатов вызовов
H_C>А что значит это: H_C>void f(...)
А это значит, что неплохо бы освежить основы языка Си.
printf видел?
int printf(const char* format, ...);
Функция, которая способна принять произвольное количество аргументов, — единственно, она не знает типы этих аргументов и лишь надеется на то, что вызывающая сторона положила туда нужные данные нужных типов в нужном количестве.
Но для функции-заглушки, которая ничего не делает, на содержимое пофиг.
Здравствуйте, x-code, Вы писали:
К>>Да любым способом утилизировать произвольное количество аргументов.
XC>Что-то эта тема (шаблоны с переменным числом аргументов) как-то вообще мимо меня прошла XC>Вы можете рассказать хоть что-то поподробнее, как оно вообще работает? XC>Как такие шаблоны разворачиваются в компиляторе? XC>Какие есть вообще способы с ними работать?
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, x-code, Вы писали:
XC>>Что-то эта тема (шаблоны с переменным числом аргументов) как-то вообще мимо меня прошла XC>>Вы можете рассказать хоть что-то поподробнее, как оно вообще работает? XC>>Как такие шаблоны разворачиваются в компиляторе? XC>>Какие есть вообще способы с ними работать?
A>и тебя в гугле забанили? попробуй тогда какой-нибудь яндекс или поиск мейл.ру
А в гугле/яндексе как эта информация появилась? Кто-то спросил, ему ответили. Почему нельзя спрашивать здесь?
Вообще странно, раньше RSDN был более дружественным, счас народ изменился
LD>А в гугле/яндексе как эта информация появилась? Кто-то спросил, ему ответили. Почему нельзя спрашивать здесь?
LD>Вообще странно, раньше RSDN был более дружественным, счас народ изменился :)
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, Lonely Dog, Вы писали:
LD>>А в гугле/яндексе как эта информация появилась? Кто-то спросил, ему ответили. Почему нельзя спрашивать здесь?
A>нет, начала написали пропозалы, потом Струструп написал C++11 FAQ, потом это скопировали в википедию на 100 языках, A>а потом набежала толпа ленивых нубов, и они начали задавать вопросы, ответы на которые написаны в википедии/FAQ
RSDN ценен контентом, а не ответами в стиле "ищи в гугле". Жаль, что ты этого не понимаешь
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, Lonely Dog, Вы писали:
LD>>А может ты перестанешь посылать людей читать книжку? X>нэд.
Печалька
Ну да ничего, может пройдет со временем
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, Lonely Dog, Вы писали:
LD>>RSDN ценен контентом, а не ответами в стиле "ищи в гугле". Жаль, что ты этого не понимаешь X>понимать это должны те, кто с этого что-то получает X>мне, и еще многим, на rsdn просто нас****, ибо выбор огромен
Я редко что-то спрашиваю на RSDN, но часто попадаются интересные дискуссии. Даже на тривиальные вопросы . Т.ч. да, я получаю.
Но дело в не том, не понимаю людей, которые не поленились и ответили в стиле "иди, читай книжки"
Здравствуйте, Lonely Dog, Вы писали:
LD>>>А в гугле/яндексе как эта информация появилась? Кто-то спросил, ему ответили. Почему нельзя спрашивать здесь?
A>>нет, начала написали пропозалы, потом Струструп написал C++11 FAQ, потом это скопировали в википедию на 100 языках, A>>а потом набежала толпа ленивых нубов, и они начали задавать вопросы, ответы на которые написаны в википедии/FAQ LD>RSDN ценен контентом, а не ответами в стиле "ищи в гугле". Жаль, что ты этого не понимаешь
контент ценен уникальностью, а копипаста или пересказ википедии — это плохой контент.
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, Lonely Dog, Вы писали:
LD>>>>А в гугле/яндексе как эта информация появилась? Кто-то спросил, ему ответили. Почему нельзя спрашивать здесь?
A>>>нет, начала написали пропозалы, потом Струструп написал C++11 FAQ, потом это скопировали в википедию на 100 языках, A>>>а потом набежала толпа ленивых нубов, и они начали задавать вопросы, ответы на которые написаны в википедии/FAQ LD>>RSDN ценен контентом, а не ответами в стиле "ищи в гугле". Жаль, что ты этого не понимаешь A>контент ценен уникальностью, а копипаста или пересказ википедии — это плохой контент.
Ничего подобного
Ты никогда не сталкивался с тем, что вот прочитал в одной книжке, понял не все. Потом прочитал в другой (другое изложение), понял. Так и здесь, один человек будет использовать одни примеры, другой другие. Я понимаю потоки в Windows (примитивы синхронизации, API и пр), кто-то другой знает Posix API (pthreads). Соответственно при ответе на один и тот же вопрос (про потоки где-нибудь еще) я буду использовать примеры из своей области знаний, другой человек из своей.
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, Lonely Dog, Вы писали:
LD>>Но дело в не том, не понимаю людей, которые не поленились и ответили в стиле "иди, читай книжки"
A>кто-то же должен был это написать
Зачем? Мне кажется, бесполезно воспитывать людей. Если кому-то удобно спросить здесь, пускай спрашивает. Всегда найдется тот, кому захочется ответить на практически на любой вопрос. 10 лет назад (я на RSDN с 2002 года) отвечали почти на все. Кроме разве что вопросов от студентов (в стиле, напишите мне лабу .
Здравствуйте, Abyx, Вы писали:
LD>>Но дело в не том, не понимаю людей, которые не поленились и ответили в стиле "иди, читай книжки" A>кто-то же должен был это написать
А высшее образование вы тоже чисто по книжкам по книжкам получали?
На самом деле завидую если так — это редкий дар. Обычно людям, чтобы чему-то научитсья, нужно ходить на лекции, конспектировать, спрашивать у преподов уточняющие вопросы, ходить на практические занятия, смотреть как сделаны лабы у товарищей, обсуждать с ними это, затем переписывать конспекты на шпаргалки, сдавать экзамены, возвращаться к пройденному материалу из других курсов, участвовать в реальных проектах...
В общем, книжки это хорошо, но недостаточно.
Вопрос про данную хитрую конструкцию вполне достойный. Я понимаю, если бы спросили как работает оператор if, или, простихосподи, goto. Или просили бы написать лабу в стиле "ввести два числа, вывести сумму двух чисел". Но тут — какая-то хитровывернутая конструкция из малоизвестных, экзотических и только-что появившихся возможностей С++. Я медитирую над этой хренью с начала появления темы и не понимаю как она работает Хотя с простыми примерами по variadic templates вроде все понятно.
Ну вот как она умудряется распространить вызов функции f на каждый элемент пакета параметров?
Здравствуйте, andy1618, Вы писали:
A>Здравствуйте, Lonely Dog, Вы писали:
LD>>Вообще странно, раньше RSDN был более дружественным, счас народ изменился
A>В данном случае, я думаю, причина другая. A>Как кто-то сказал, "резкость в высказываниях — удел молодости"
Да, тоже об этом подумал .
Здравствуйте, x-code, Вы писали:
XC>Ну вот как она умудряется распространить вызов функции f на каждый элемент пакета параметров?
по определению.
14.5.3[temp.variadic]
4 A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below).
[...]
7 The instantiation of a pack expansion [...] produces a list E1, E2, ..., EN, where N is the number of elements in the pack expansion parameters. Each Ei is generated by instantiating the pattern and replacing each pack expansion parameter with its ith element.
есть паттерн, он копируется для каждого элемента пака. просто же
Здравствуйте, Lonely Dog, Вы писали:
LD> У меня тупо нет времени изучать новые возможности C++. Узнаю про них из таких вот постов.
На посты-то время находится... А в книжке концентрация полезной информации, как правило, больше.
Здравствуйте, DarkEld3r, Вы писали:
DE>Здравствуйте, Lonely Dog, Вы писали:
LD>> У меня тупо нет времени изучать новые возможности C++. Узнаю про них из таких вот постов. DE>На посты-то время находится... А в книжке концентрация полезной информации, как правило, больше.
Ну одно дело раз в день пробежаться по заголовкам, выбрать пару интересных. Другое дело читать книжки. Мне как бы база не сильно интересна, да и в книжках не все пишут, только основные вещи.
Здравствуйте, Nikе, Вы писали:
N>Как бы да. Просто сначала появилась версия, что такая форма как-то позволяет специфицировать порядок вызовов. Иначе совсем непонятно — зачем она нужна.
Ну параллелить, например, удобно автоматом...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском