[FYI] С++17: Генерация визитера для std::variant на лету
От: Анатолий Широков СССР  
Дата: 02.10.17 16:35
Оценка: 73 (8)
Сегодня на cppreference наткнулся на пример создания визитера для std::visit на лету:

#include <string>
#include <variant>
#include <iostream>

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

int main() {
    std::variant<int, double, std::string> v = {std::string{"10"}};
    std::visit(overloaded {
            [](auto arg) { std::cout << arg << ' '; },
            [](double arg) { std::cout << std::fixed << arg << ' '; },
            [](const std::string& arg) { std::cout << "\"" << arg << "\"" << ' '; },
        }, v);
}


Красиво!
std::variant std::visit
Re: [FYI] С++17: Генерация визитера для std::variant на лету
От: Шахтер Интернет  
Дата: 02.10.17 16:44
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Сегодня на cppreference наткнулся на пример создания визитера для std::visit на лету:


АШ>
АШ>#include <string>
АШ>#include <variant>
АШ>#include <iostream>

АШ>template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
АШ>template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

АШ>int main() {
АШ>    std::variant<int, double, std::string> v = {std::string{"10"}};
АШ>    std::visit(overloaded {
АШ>            [](auto arg) { std::cout << arg << ' '; },
АШ>            [](double arg) { std::cout << std::fixed << arg << ' '; },
АШ>            [](const std::string& arg) { std::cout << "\"" << arg << "\"" << ' '; },
АШ>        }, v);
АШ>}
АШ>


АШ>Красиво!


К сожалению, довольно часто хочется полиморфного функтора с общей капчей. Приходится писать класс. А иначе дублируются данные.
Было бы хорошо иметь такой синтаксис

auto func = [&out] (int a) { Printf(out,"#8;",a); }
                   (const char *str) { Printf(out,"#32;",str); } ;
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: [FYI] С++17: Генерация визитера для std::variant на лету
От: Voivoid Россия  
Дата: 02.10.17 20:20
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Сегодня на cppreference наткнулся на пример создания визитера для std::visit на лету:

АШ>Красиво!

Есть ж boost::make_overloaded_function. В общем-то все тоже самое можно сделать
Re: [FYI] С++17: Генерация визитера для std::variant на лету
От: rg45 СССР  
Дата: 03.10.17 09:58
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>
АШ>template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
АШ>template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
АШ>


Похоже, отстал я от жизни. Это что за фича, похожая на объявление внешнего конструктора? Где почитать, подскажите, пожалуйста.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: [FYI] С++17: Генерация визитера для std::variant на лету
От: reversecode google
Дата: 03.10.17 10:37
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>
АШ>>template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
АШ>>template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
АШ>>


R>Похоже, отстал я от жизни. Это что за фича, похожая на объявление внешнего конструктора? Где почитать, подскажите, пожалуйста.


искал весь кейс
нашел что то отдаленно похожее
http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0051r2.pdf
но меня интересовало другое
Re: [FYI] С++17: Генерация визитера для std::variant на лету
От: reversecode google
Дата: 03.10.17 10:39
Оценка:
АШ>
АШ>template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

АШ>


расскажите по эту конструкцию
это 17 стандарт ?
краткая запись того что функция overloaded возвращает структуру оверлоадед ? тело автоматом создастся ?
или это только декларация без тела ?
Re[2]: [FYI] С++17: Генерация визитера для std::variant на лету
От: night beast СССР  
Дата: 03.10.17 10:47
Оценка: 15 (2)
Здравствуйте, rg45, Вы писали:

АШ>>
АШ>>template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
АШ>>template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
АШ>>


R>Похоже, отстал я от жизни. Это что за фича, похожая на объявление внешнего конструктора? Где почитать, подскажите, пожалуйста.


это правило для авто вывода типа.
Template argument deduction for class templates
Re[2]: [FYI] С++17: Генерация визитера для std::variant на л
От: night beast СССР  
Дата: 03.10.17 10:51
Оценка:
Здравствуйте, reversecode, Вы писали:

R>расскажите по эту конструкцию

R>это 17 стандарт ?
R>краткая запись того что функция overloaded возвращает структуру оверлоадед ? тело автоматом создастся ?
R>или это только декларация без тела ?

декларация.
на ее основании автоматически выводятся типы шаблонных параметров template<class... Ts> у класса,
чтобы можно было просто писать overloaded вместо overloaded<T1, T2, ...>
Отредактировано 03.10.2017 10:52 night beast . Предыдущая версия .
Re[3]: [FYI] С++17: Генерация визитера для std::variant на л
От: reversecode google
Дата: 03.10.17 11:02
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, reversecode, Вы писали:


R>>расскажите по эту конструкцию

R>>это 17 стандарт ?
R>>краткая запись того что функция overloaded возвращает структуру оверлоадед ? тело автоматом создастся ?
R>>или это только декларация без тела ?

NB>декларация.

NB>на ее основании автоматически выводятся типы шаблонных параметров template<class... Ts> у класса,
NB>чтобы можно было просто писать overloaded вместо overloaded<T1, T2, ...>

все бы ничего, но я не вижу где используется функция overloaded(Ts...) что бы по не что то выводить
в std::visitor передается сама структура overloaded с инициализацией лямбд
Re[4]: [FYI] С++17: Генерация визитера для std::variant на л
От: night beast СССР  
Дата: 03.10.17 11:03
Оценка:
Здравствуйте, reversecode, Вы писали:

R>все бы ничего, но я не вижу где используется функция overloaded(Ts...) что бы по не что то выводить

R>в std::visitor передается сама структура overloaded с инициализацией лямбд

это не функция.
подробнее здесь. Explicitly specified Deduction Guide.
Отредактировано 03.10.2017 11:04 night beast . Предыдущая версия .
Re[5]: [FYI] С++17: Генерация визитера для std::variant на л
От: reversecode google
Дата: 03.10.17 11:13
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, reversecode, Вы писали:


R>>все бы ничего, но я не вижу где используется функция overloaded(Ts...) что бы по не что то выводить

R>>в std::visitor передается сама структура overloaded с инициализацией лямбд

NB>это не функция.

NB>подробнее здесь. Explicitly specified Deduction Guide.

ну теперь если правильно понял это конструктор, а "->" не возвращаемое значение а правило для вывода типа в конструкторе

если так, то странно почему вообще не упростили без второй строчки, если вариадики есть уже в шаблоне типа, то само собой должен автоматом быть и конструктор для такого
Re[2]: [FYI] С++17: Генерация визитера для std::variant на л
От: Анатолий Широков СССР  
Дата: 03.10.17 11:28
Оценка: 18 (1) +1
Здравствуйте, rg45, Вы писали:

R>Похоже, отстал я от жизни. Это что за фича, похожая на объявление внешнего конструктора? Где почитать, подскажите, пожалуйста.


Это class template argument deduction guide http://en.cppreference.com/w/cpp/language/class_template_argument_deduction Фича, которая позволяет опускать аргументы шаблона

std::pair p {1, 10};
Отредактировано 03.10.2017 11:29 Анатолий Широков . Предыдущая версия .
Re[6]: [FYI] С++17: Генерация визитера для std::variant на л
От: night beast СССР  
Дата: 03.10.17 11:31
Оценка: +1
Здравствуйте, reversecode, Вы писали:

R>>>все бы ничего, но я не вижу где используется функция overloaded(Ts...) что бы по не что то выводить

R>>>в std::visitor передается сама структура overloaded с инициализацией лямбд

NB>>это не функция.

NB>>подробнее здесь. Explicitly specified Deduction Guide.

R>ну теперь если правильно понял это конструктор, а "->" не возвращаемое значение а правило для вывода типа в конструкторе


это правило. но конструктора нет.
после того как получен тип, скорее всего, просто работает aggregate initialization.

R>если так, то странно почему вообще не упростили без второй строчки, если вариадики есть уже в шаблоне типа, то само собой должен автоматом быть и конструктор для такого


наличие вариадика в шаблоне не означает существования конструктора для него.
собственно в примере этого конструктора и нет.
ну, по крайней мере я так думаю
Re[6]: [FYI] С++17: Генерация визитера для std::variant на л
От: Анатолий Широков СССР  
Дата: 03.10.17 11:42
Оценка:
Здравствуйте, reversecode, Вы писали:

R>ну теперь если правильно понял это конструктор, а "->" не возвращаемое значение а правило для вывода типа в конструкторе


R>если так, то странно почему вообще не упростили без второй строчки, если вариадики есть уже в шаблоне типа, то само собой должен автоматом быть и конструктор для такого


У нас нет конструктора, который бы принимал

        {
            [](auto arg) { std::cout << arg << ' '; },
            [](double arg) { std::cout << std::fixed << arg << ' '; },
            [](const std::string& arg) { std::cout << "\"" << arg << "\"" << ' '; },
        }


поэтому нужен deduction guide.
Re[7]: [FYI] С++17: Генерация визитера для std::variant на л
От: reversecode google
Дата: 03.10.17 11:51
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, reversecode, Вы писали:


R>>>>все бы ничего, но я не вижу где используется функция overloaded(Ts...) что бы по не что то выводить

R>>>>в std::visitor передается сама структура overloaded с инициализацией лямбд

NB>>>это не функция.

NB>>>подробнее здесь. Explicitly specified Deduction Guide.

R>>ну теперь если правильно понял это конструктор, а "->" не возвращаемое значение а правило для вывода типа в конструкторе


NB>это правило. но конструктора нет.

NB>после того как получен тип, скорее всего, просто работает aggregate initialization.

R>>если так, то странно почему вообще не упростили без второй строчки, если вариадики есть уже в шаблоне типа, то само собой должен автоматом быть и конструктор для такого


NB>наличие вариадика в шаблоне не означает существования конструктора для него.

NB>собственно в примере этого конструктора и нет.
NB>ну, по крайней мере я так думаю

по примеру я как раз таки и решил что это конструтор

[Example:
template<class T> struct container {
container(T t) {}
template<class Iter> container(Iter beg, Iter end);
};
template<class Iter>
container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>;
std::vector<double> v = { /* ... */};

container c(7); // OK. Deduces int for T
auto d = container(v.begin(), v.end()); // OK. Deduces double for T
container e{5, 6}; // Ill-formed. int is not an iterator
— end example]


судя по этому примеру как раз для конструктора container(Iter beg, Iter end)
и выводят тип, точнее по конструктору выводят Т
уточнив специализацию шаблоном
template<class Iter>
container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>;

а в примере std::visit как раз через вариадик конструктор набиваются ламбды
и что бы этот вариадик конструктор сработал и уточняют правилом вывода

вот как я это понял теперь для себя

может к с++20 додумаются что имея вариадик шаблон, само собой может быть и вариадик конструктор и второе правило вывода если тип шаблона не задан для конструктора отдельно, можно будет опускать
Re[8]: [FYI] С++17: Генерация визитера для std::variant на л
От: night beast СССР  
Дата: 03.10.17 11:58
Оценка:
Здравствуйте, reversecode, Вы писали:

NB>>наличие вариадика в шаблоне не означает существования конструктора для него.

NB>>собственно в примере этого конструктора и нет.
NB>>ну, по крайней мере я так думаю

под примером я имел в виду тот что в начальном сообщении.
в том что в пропосале, конструктор присутствует.

R>по примеру я как раз таки и решил что это конструтор


R>судя по этому примеру как раз для конструктора container(Iter beg, Iter end)

R>и выводят тип, точнее по конструктору выводят Т
R>уточнив специализацию шаблоном
R>template<class Iter>
R>container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>;

здесь все верно.

R>а в примере std::visit как раз через вариадик конструктор набиваются ламбды

R>и что бы этот вариадик конструктор сработал и уточняют правилом вывода

чуть упрощу.
struct t1 {};
struct t2 {};

struct test : t1, t2 {};

test x = { t1(), t2() };

конструктора нет, однако х инициализируется.
Re[7]: [FYI] С++17: Генерация визитера для std::variant на л
От: _hum_ Беларусь  
Дата: 03.10.17 18:08
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, reversecode, Вы писали:


R>>ну теперь если правильно понял это конструктор, а "->" не возвращаемое значение а правило для вывода типа в конструкторе


NB>это правило. но конструктора нет.

NB>после того как получен тип, скорее всего, просто работает aggregate initialization.

night beast, так а точно нельзя это воспринимать как именно что возвращаемое конструктором значение-объект? если нет, то с вашей точки зрения, какой смысл использовать для этой конструкции уже закрепленный ранее символ "->" (неужели нельзя было другой найти, наподобие "->>" или еще чего)
Re[8]: [FYI] С++17: Генерация визитера для std::variant на л
От: rg45 СССР  
Дата: 03.10.17 18:39
Оценка: +1
Здравствуйте, _hum_, Вы писали:

__>night beast, так а точно нельзя это воспринимать как именно что возвращаемое конструктором значение-объект? если нет, то с вашей точки зрения, какой смысл использовать для этой конструкции уже закрепленный ранее символ "->" (неужели нельзя было другой найти, наподобие "->>" или еще чего)


Воспринимать, конечно, можно что угодно и как угодно. Но реальность такова, что у конструкторов нет возвращаемых значений. Говоря популярным языком, конструктор — это процедура, создающая объект на выделенном участке памяти.

Говоря же об упомянутой выше class template argument deduction guide, опять же популярным языком: эту фичу следует расматривать не как конструктор, а как средство, предоставляющее возможность конструирования объекта шаблонного класса без явной спецификации фактических параметров шаблона. Определение правила автоматического выведения типов парамеров не заменяет соответсвующий конструктор (не важно, сгенерированный ли компилятором или определенный пользователем), а наоборот, предполагает его существование и доступность!
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 03.10.2017 18:45 rg45 . Предыдущая версия .
Re[8]: [FYI] С++17: Генерация визитера для std::variant на л
От: night beast СССР  
Дата: 03.10.17 19:33
Оценка:
Здравствуйте, _hum_, Вы писали:

R>>>ну теперь если правильно понял это конструктор, а "->" не возвращаемое значение а правило для вывода типа в конструкторе


NB>>это правило. но конструктора нет.

NB>>после того как получен тип, скорее всего, просто работает aggregate initialization.

__>night beast, так а точно нельзя это воспринимать как именно что возвращаемое конструктором значение-объект? если нет, то с вашей точки зрения, какой смысл использовать для этой конструкции уже закрепленный ранее символ "->" (неужели нельзя было другой найти, наподобие "->>" или еще чего)


ну, я написал свое понимание ситуации.
почему использовали "->"? видимо затем, чтобы не выдумывать новый синтаксис.
Re[9]: [FYI] С++17: Генерация визитера для std::variant на л
От: _hum_ Беларусь  
Дата: 03.10.17 20:17
Оценка: -2
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, _hum_, Вы писали:


__>>night beast, так а точно нельзя это воспринимать как именно что возвращаемое конструктором значение-объект? если нет, то с вашей точки зрения, какой смысл использовать для этой конструкции уже закрепленный ранее символ "->" (неужели нельзя было другой найти, наподобие "->>" или еще чего)


R>Воспринимать, конечно, можно что угодно и как угодно. Но реальность такова, что у конструкторов нет возвращаемых значений. Говоря популярным языком, конструктор — это процедура, создающая объект на выделенном участке памяти.


ммм.. это по стандарту. но никто не мешает воспринмать конструктор как функцию, инициализирующую созданный объкт, а после возвращающую ссылку на него же (как в операторе присваивания), просто программисту это возращаемое значение недоступно и не видно
[ведь должна же быть причина, по которой разработчики оставили ->, а не ввели новый символ]

R>Говоря же об упомянутой выше class template argument deduction guide, опять же популярным языком: эту фичу следует расматривать не как конструктор, а как средство, предоставляющее возможность конструирования объекта шаблонного класса без явной спецификации фактических параметров шаблона. Определение правила автоматического выведения типов парамеров не заменяет соответсвующий конструктор (не важно, сгенерированный ли компилятором или определенный пользователем), а наоборот, предполагает его существование и доступность!


ну, если попытаться на минуточку посмотреть с точки зрения того, что то было все-таки подобием декларации конструктора, то вроде все становится естественным — можно тогда считать, что компилятор просто, пользуясь имеющейся декларацией, осуществляет вывод типа шаблона через механизм наподобие deduction from a function call
Отредактировано 03.10.2017 20:21 _hum_ . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.