Perfect forward, как ?
От: Videoman Россия https://hts.tv/
Дата: 23.10.19 07:54
Оценка:
Добрый день всем любителям современного С++ 17.
В процессе разработки сложного библиотечного кода возникли вопросы. Код сильно упрощен:
    template <typename Callable, typename ...Params>
    void Func(Params&& ...params) 
    {
        auto Func2 = [](auto&&... params)
        {
            Callable(params...); // Как тут сделать forward_reference ???
        };

        Func2(std::forward<Params>(params)...);
    }

Я в курсе что пока шаблонных лямбд нет, поэтому:
1. Как всегда я туплю на ровном месте?
2. Это косяк стандарта и это не возможно сделать "прямо", так как в С++ опять чего-то не подвезли?
3. Это делается так, как я это исправил сейчас — написал шаблонный объект функтор руками?
Отредактировано 23.10.2019 8:48 Videoman . Предыдущая версия .
Re: Perfect forward, как ?
От: rg45 СССР  
Дата: 23.10.19 08:06
Оценка: 13 (2) +2
Здравствуйте, Videoman, Вы писали:

V>Добрый день всем любителям современного С++ 17.

V>В процессе разработки сложного библиотечного кода возникли вопросы. Код сильно упрощен:
V>
V>    template <typename Callable, typename ...Params>
V>    void Func(Params&& ...params) 
V>    {
V>        auto Func2 = [](auto&&... params)
V>        {
V>            Callable(params...); // Как тут сделать forward_reference ???
V>        };

V>        Func2(std::forward<Params>(params...));
V>    }
V>


Начнем с главного, как сделать forward reference. Очень просто:

Callable(std::forward<decltype(params)>(params)...);


V>Я в курсе что пока шаблонных лямбд нет, поэтому:


То, что ты написал, это и есть шаблонная лямбда, а точнее класс с шаблонным оператором operator(). С тем лишь преимуществом, что определение рукописных шаблонов, ни в каком виде, не разрешено в области видимости функций.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 23.10.2019 8:08 rg45 . Предыдущая версия .
Re[2]: Perfect forward, как ?
От: Videoman Россия https://hts.tv/
Дата: 23.10.19 08:46
Оценка:
Здравствуйте, rg45, Вы писали:

R>То, что ты написал, это и есть шаблонная лямбда, а точнее класс с шаблонным оператором operator(). С тем лишь преимуществом, что определение рукописных шаблонов, ни в каком виде, не разрешено в области видимости функций.


Просто, я знаю что правила вывода типов для decltype и для шаблонов отличаются и я не был уверен что decltype(params) даст тот же результат. Мне нужно было подтверждение. Также я в курсе про рукописные шаблоны, но в моем случае я не видел другого выхода.
Тесты сработали. Спасибо большое!
Re[3]: Perfect forward, как ?
От: rg45 СССР  
Дата: 23.10.19 09:05
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Просто, я знаю что правила вывода типов для decltype и для шаблонов отличаются и я не был уверен что decltype(params) даст тот же результат.


Тема и правда интересная. Далеко не все знают разницу между decltype(params) и decltype((params)) и могут толком объяснить, почему для std::forward нужно явно указывать тип, в то время как std::move определяет тип автоматически. Ну и т.п.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Perfect forward, как ?
От: Videoman Россия https://hts.tv/
Дата: 23.10.19 14:09
Оценка:
Здравствуйте, rg45, Вы писали:

R>Тема и правда интересная. Далеко не все знают разницу между decltype(params) и decltype((params)) и могут толком объяснить, почему для std::forward нужно явно указывать тип, в то время как std::move определяет тип автоматически. Ну и т.п.


Ну у меня эта проблема, собственно, вылезла, когда в руках оказывался std::tuple<> с форвард ссылками и потом с ним вызывался std::apply. И тут я с большим сожалением обнаружил, что std::apply нельзя вызвать для метода класса, типа:
std::apply(&Class::Method, this, std::move(rparams_in_tuple));
Кстати, для std::invoke — можно, но у меня в руках только std::tuple<>. Пришлось городить лямбду.
Re[5]: Perfect forward, как ?
От: PM  
Дата: 23.10.19 19:14
Оценка: 15 (2)
Здравствуйте, Videoman, Вы писали:

V>Ну у меня эта проблема, собственно, вылезла, когда в руках оказывался std::tuple<> с форвард ссылками и потом с ним вызывался std::apply. И тут я с большим сожалением обнаружил, что std::apply нельзя вызвать для метода класса, типа:

V>
V>std::apply(&Class::Method, this, std::move(rparams_in_tuple));
V>
Кстати, для std::invoke — можно, но у меня в руках только std::tuple<>. Пришлось городить лямбду.


Похоже, что можно, если создать новый кортеж, в котором первым элементом будет объект:
std::apply(&Class::MemFun, std::tuple_cat(std::make_tuple(classInstance), paramsTuple));


https://stackoverflow.com/a/44777135/1355844
Re[6]: Perfect forward, как ?
От: Videoman Россия https://hts.tv/
Дата: 24.10.19 08:47
Оценка: +1 :)
Здравствуйте, PM, Вы писали:

PM>Похоже, что можно, если создать новый кортеж, в котором первым элементом будет объект:

PM>
PM>std::apply(&Class::MemFun, std::tuple_cat(std::make_tuple(classInstance), paramsTuple));
PM>

Вот спасибо вам большое! Теперь все встает на свои места. Суперсиметрия вселенной восстановлена .
P.S. Ну ничего, зато куча пробелов в знаниях заполнилась.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.