Pull to refresh

Comments 17

Отличная статья по достаточно сложной теме, спасибо!
Но есть несколько замечаний:
1. Замените NULL на nullptr(раз уж С++0x так пусть будет везде)
2. Какая-то проблема с комментариями, Ю они обрезаны в коде. Т.е. комментарии больше определенной длины не закончены
3. Добавьте где это можно собрать(если можно где-то)
В плане сборки не знаю точно, надо глядеть gcc с девелоперской ветки.
Спасибо. :)

1 — если пофиксить, то пример не будет собираться ни одним из отрелизиных в настоящий момент компиляторов.
2 — пофикшу.
3 — собрать в полном объёме (вместе с лямбдами) можно с помощью gcc 4.5 и gcc 4.6 (который сейчас только разрабатывается). Без лямбд — начиная с gcc 4.3. Собственно, NULL в коде появился из за того, что nullptr в gcc 4.5 не поддерживается (а вот в 4.6 уже есть).
#define nullptr NULL
:)
Оказывается приятные вещи появились в новом стандарте С++. Спасибо за статью.
И спасибо Александреску. Его труды не пропали даром.
Да, вещи появились действительно приятные. К сожалению (по крайней мере моему) некоторые из них не в достаточной степени доведены до кондиции.
Полезная вещь действительно. Сам столкнулся с такой необходимостью недавно. Использовал TYPE_LIST из библиотеки Александреску.
«При раскрытии пакетов можно применять более сложные паттерны. Например, в приведённом выше коде можно сделать следующую замену:
template<int… Nums>
int NumsPack<Nums ...>::m_nums[] = {Nums * 10 ...};

что приведёт к выводу на экран другой последовательности:
10 20 30 40 50»

— ? 100 200 300 400 500

мне понравилась, хорошая лаконичная статья!
Вы, конечно же, правы. У меня в тексте опечатка.
А можно ли реализовать делегат с использованием varadic templates, чтобы явно не указывать типы в угловых скобках при инициализации объекта?
В смысле? Не совсем понял суть вопроса.
Чтобы в коде можно было писать:

class A
{
public:
void f1(int){};
void f2(int, int){};
};

A oA;

Delegate oDelegate1(&oA, &A::f1);
Delegate oDelegate2(&oA, &A::f2);

а не

Delegate<void (A::*)(int)> oDelegate1(&oA, &A::f1);
Delegate<void (A::*)(int, int)> oDelegate2(&oA, &A::f2);

грубо говоря, чтобы типы выводились из сигнатуры вызова конструктора.
В статье, на которую я ссылался описывается способ, с использованием интерфейса, там есть потеря производительности, связанная с виртуальным вызовом, но и по аналогии я не смог реализовать на varadic templates. Для меня открытием в этой статье стало использования вот такой формы unpacking — class Composer: public DataHolder<_ZZ> …, знал только о такой class Composer: public _ZZ …, плюс как сгенирировать последовательность чисел, попробую реализовать delegat с новыми способами понимания varadic templates.Еще раз спасибо за статью, очень классная!
Теперь понятно. Но ведь никто не мешает вам использовать следующие методы:
1. auto:
auto oDelegate1 = MakeDelegate(&oA, &A::f1);
auto oDelegate2 = MakeDelegate(&oA, &A::f2);
2. decltype:
decltype(MakeDelegate(nullptr, &A::f1)) oDelegate1;
decltype(MakeDelegate(nullptr, &A::f2)) oDelegate1;

Второй вариант можно использовать при объявлении членов класса. Вот как-то так.
Спасибо большое, вы задействовали многое из новых возможностей С++, я тут эксперементирую на Visual Studio 2012 November CP100, вот пока и пытаюсь ограничивать себя в возможностях, например ваш код из второй части статьи не смог там скомпилироваться, вот эта строчка ему не нравится: typedef decltype(m_op((*(F*)NULL)(0)...)) result_t; Но у меня будет возможность скоро и с gcc поработать.Спасибо еще раз за пищу для размышления!
Собственно, в этом заключается основная причина, по которой я практически перестал использовать MSVC в своих проектах. Для таких экспериментов gcc и clang подходят куда как лучше. :) Сейчас использую связку QtCreator + mingw gcc. Удачи вам в ваших экспериментах!
«и композитор готов. Пара примеров его использования:
auto f = MakeOp(test_opr, fn1, fn2);
auto ff = MakeOp(test_opr3, fn1, fn2, fn3);
auto ff1 = MakeOp(test_opr3, fn1, fn2, [=](int x) {return f(x) * 5;}); // здесь последним параметром в композитор передаётся лямбда-функция.»
вместо MakeOp->Composer
template<typename… T>
bool HasPositives(T… nums)
 {
     bool ret_val = true;
     ignore(ret_val = ret_val && nums >= 0 ...);
    return ret_val;
 }

Это до сих пор не работает в MSVS 2017. clang на это выдаёт в принципе справедливое предупреждение про неопределенный порядок вычисления аргументов
Sign up to leave a comment.

Articles