Re[2]: Философско-практические вопросы про метапрограммирование
От: σ  
Дата: 09.02.23 16:05
Оценка:
R>Прежде, чем ответить на основной вопрос, сразу хочу сделать одно замечание, от которого мне просто трудно удержаться. Продемонстрированный подход — это подход двадцатилетней давности, когда в набор инструментов метапрограммирования входили только overload resolution и оператор sizeof. Сейчас этот набор немного побогаче и эта же самая мета-функция может быть реализована значительно элегантнее

В книге примерно это пишут, ОП, видимо, не разобрался
Re[8]: Философско-практические вопросы про метапрограммирова
От: sergii.p  
Дата: 09.02.23 16:20
Оценка:
Здравствуйте, rg45, Вы писали:

R>
R>template <typename T>
R>auto consider_sorted_range(const T&) -> std::false_type;

R>// For standard containers, the traits must be defined beforehand
R>template <typename K, typename T, typename C, typename A>
R>auto consider_sorted_range(const std::map<K, T, C, A>&) -> std::true_type;

R>template <typename K, typename T, typename C, typename A>
R>auto consider_sorted_range(const std::multimap<K, T, C, A>&) -> std::true_type;

R>template <typename T, typename C, typename A>
R>auto consider_sorted_range(const std::set<T, C, A>&) -> std::true_type;

R>template <typename T, typename C, typename A>
R>auto consider_sorted_range(const std::multiset<T, C, A>&) -> std::true_type;

R>template <typename T>
R>using is_sorted_container = decltype(consider_sorted_range(std::declval<T>()));

R>


можно несколько короче

template <typename, template <typename...> typename>
struct is_instance : std::false_type {};

template <typename T, template <typename...> typename U>
struct is_instance<U<T>, U> : std::true_type {};

template <typename T>
using is_sorted_container = std::bool_constant<is_instance<T, std::set>::value
                                            && is_instance<T, std::map>::value
                                            && is_instance<T, std::multi_map>::value
                                            && is_instance<T, std::multi_set>::value>;
Re[9]: Философско-практические вопросы про метапрограммирова
От: rg45 СССР  
Дата: 09.02.23 16:29
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>можно несколько короче


SP>
SP>template <typename, template <typename...> typename>
SP>struct is_instance : std::false_type {};

SP>template <typename T, template <typename...> typename U>
SP>struct is_instance<U<T>, U> : std::true_type {};

SP>template <typename T>
SP>using is_sorted_container = std::bool_constant<is_instance<T, std::set>::value
SP>                                            && is_instance<T, std::map>::value
SP>                                            && is_instance<T, std::multi_map>::value
SP>                                            && is_instance<T, std::multi_set>::value>;
SP>


Нельзя. Возможность кастомизации для пользовательских типов тут же накроется. Там же ниже по коду специально пример использования:

struct MySortedContainer
{

};
auto assume_sorted_range(const MySortedContainer&) -> std::true_type;
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[8]: Философско-практические вопросы про метапрограммирова
От: Максим Россия  
Дата: 09.02.23 16:32
Оценка: +1
R>Ну, примерно вот так.

Класс!!! Спасибо большое, особенно за то, что показали как можно применять в реальной жизни "User-defined deduction guides". Не видел такого раньше!
Errare humanum est
Re[9]: Философско-практические вопросы про метапрограммирова
От: rg45 СССР  
Дата: 09.02.23 16:36
Оценка:
Здравствуйте, Максим, Вы писали:

М>Класс!!! Спасибо большое, особенно за то, что показали как можно применять в реальной жизни "User-defined deduction guides". Не видел такого раньше!


На здоровье! Обращайся, если что.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[9]: Философско-практические вопросы про метапрограммирова
От: rg45 СССР  
Дата: 09.02.23 20:30
Оценка: 1 (1)
Здравствуйте, Максим, Вы писали:

М>Класс!!! Спасибо большое, особенно за то, что показали как можно применять в реальной жизни "User-defined deduction guides". Не видел такого раньше!


Еще хочу сказать об одной "мелочи" вдогонку, про которую часто забывают. Когда пишешь какую-то обобщенную функцию, для всех возможных вариантов ее специализаций/перегрузок, нужно задаваться вопросом, в каком месте будет возникать ошибка, в случае неправильного использования. Например, при попытке вызвать метод sort для константного объекта (массива или стандартного контейнера), очень важно, чтобы ошибка компиляции возникала в клиентском коде, именно в том месте, где осуществляется попытка сделать неправильный вызов, а не где-то в потрохах библиотечного кода. А для этого нужно хорошо продумывать реализацию всех метафункций и состав фильтров SFINAE.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.02.2023 10:23 rg45 . Предыдущая версия . Еще …
Отредактировано 09.02.2023 20:37 rg45 . Предыдущая версия .
Отредактировано 09.02.2023 20:31 rg45 . Предыдущая версия .
Re[9]: Философско-практические вопросы про метапрограммирова
От: Максим Россия  
Дата: 10.02.23 05:51
Оценка:
SP>можно несколько короче

SP>
SP>template <typename, template <typename...> typename>
SP>struct is_instance : std::false_type {};

SP>template <typename T, template <typename...> typename U>
SP>struct is_instance<U<T>, U> : std::true_type {};

SP>template <typename T>
SP>using is_sorted_container = std::bool_constant<is_instance<T, std::set>::value
SP>                                            && is_instance<T, std::map>::value
SP>                                            && is_instance<T, std::multi_map>::value
SP>                                            && is_instance<T, std::multi_set>::value>;
SP>


Спасибо за вариант!
Тут я так понимаю опечатка, вместо && должно быть ||.
И подскажите, пожалуйста, что это за синтаксис
template <typename T, template <typename...> typename U> struct is_instance<U<T>, U> : std::true_type {}


Что-то типа nested templates? Еще вот эти точки от variadic templates смущают.
Errare humanum est
Re[2]: Философско-практические вопросы про метапрограммирование
От: B0FEE664  
Дата: 10.02.23 17:59
Оценка:
Здравствуйте, cppguard, Вы писали:

C> пусть твои сомнения развеют Торвальдс и Беллар. Один написал классную операционку, а второй делает потрясающие проекты в одиночку. И оба не пишут на С++.


А вы пробовали читать их код?
И каждый день — без права на ошибку...
Re[7]: Философско-практические вопросы про метапрограммирова
От: ботаныч Интернет https://youtube.com/shorts/eapWB7W8hEE
Дата: 11.02.23 05:31
Оценка: 4 (1)
Здравствуйте, Максим, Вы писали:

М>А можете, если есть время, более подробно написать

почитав код ниже, мне хочется вопрос задать. Вам это в каком контексте надо? Если для продакшин кода, то специфика одна, если для библиотечного кода, да еще и header only подход будет сршенно разным, для нового продакшин кода, подход rg45 достаточно лаконичен, где стандарт и набор компиляторов практически предопределен и меняется довольно редко (хотя и там будут вопросы по скорости компиляции, иногда короткие лаконичные вещи компилируются дольше). Если же это библиотечный код, то часто предпочтение отдается дедовским версиям SFINAE громоздким, но покрывающим большее количество компиляторов. Также Вам может понадобиться столкнуться с периодом — до variadic templates.

М>UPD

М>Еще, наверно, можно попробовать оттолкнуться от std::is_same_v<T, std::set>
namespace hl = std;
template <template <typename... > class Tmp> struct holder {};

template <typename T> struct extract : hl::false_type {};

template <typename... Ts, template <typename... > class Tmpl>
struct extract<Tmpl<Ts...>> : hl::true_type
{
    typedef holder<Tmpl> type;
};
 
int main()
{
  enum {v = std::is_same<typename extract<T>::type, holder<std::set>>::value};
}
Re[8]: Философско-практические вопросы про метапрограммирова
От: rg45 СССР  
Дата: 11.02.23 11:11
Оценка:
Здравствуйте, ботаныч, Вы писали:

М>>А можете, если есть время, более подробно написать

Б> почитав код ниже, мне хочется вопрос задать. Вам это в каком контексте надо? Если для продакшин кода, то специфика одна, если для библиотечного кода, да еще и header only подход будет сршенно разным, для нового продакшин кода, подход rg45 достаточно лаконичен, где стандарт и набор компиляторов практически предопределен и меняется довольно редко (хотя и там будут вопросы по скорости компиляции, иногда короткие лаконичные вещи компилируются дольше). Если же это библиотечный код, то часто предпочтение отдается дедовским версиям SFINAE громоздким, но покрывающим большее количество компиляторов. Также Вам может понадобиться столкнуться с периодом — до variadic templates.

М>>UPD

М>>Еще, наверно, можно попробовать оттолкнуться от std::is_same_v<T, std::set>
Б>
Б>namespace hl = std;
Б>template <template <typename... > class Tmp> struct holder {};

Б>template <typename T> struct extract : hl::false_type {};

Б>template <typename... Ts, template <typename... > class Tmpl>
Б>struct extract<Tmpl<Ts...>> : hl::true_type
Б>{
Б>    typedef holder<Tmpl> type;
Б>};
 
Б>int main()
Б>{
Б>  enum {v = std::is_same<typename extract<T>::type, holder<std::set>>::value};
Б>}
Б>


И как потом с этим подходом можно будет расширять правила для пользовательских типов, находящихся в клиенстких простраствах имен? Например, как можно(нужно) переписать вот этот фрагмент:

http://coliru.stacked-crooked.com/a/94e3814cbca1fdad

namespace lib_01 {

template <typename T>
using is_sorted_container = decltype(assume_sorted_range(std::declval<T>()));

} // namespace lib_01

namespace app_01 {
namespace app_02 {
namespace app_03 {

struct MySortedContainer
{

};
auto assume_sorted_range(const MySortedContainer&) -> std::true_type;

} // namespace app_03
} // namespace app_02
} // namespace app_01


Теперь по поводу "покрывающим большее количество компиляторов": можешь показать ХОТЯ БЫ ОДИН компилятор, на котором твой пример компилируется, а мой нет?

А просадка времени компиляции откуда возьмется (по сравнению с твоим вариантом)? Объявления функций все просадят что ли?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 11.02.2023 12:03 rg45 . Предыдущая версия . Еще …
Отредактировано 11.02.2023 12:00 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 11:47 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 11:46 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 11:12 rg45 . Предыдущая версия .
Re[8]: Философско-практические вопросы про метапрограммирова
От: rg45 СССР  
Дата: 11.02.23 11:23
Оценка:
Здравствуйте, ботаныч, Вы писали:

Б>Здравствуйте, Максим, Вы писали:


М>>А можете, если есть время, более подробно написать

Б> почитав код ниже, мне хочется вопрос задать. Вам это в каком контексте надо? Если для продакшин кода, то специфика одна, если для библиотечного кода, да еще и header only подход будет сршенно разным, для нового продакшин кода, подход rg45 достаточно лаконичен, где стандарт и набор компиляторов практически предопределен и меняется довольно редко (хотя и там будут вопросы по скорости компиляции, иногда короткие лаконичные вещи компилируются дольше). Если же это библиотечный код, то часто предпочтение отдается дедовским версиям SFINAE громоздким, но покрывающим большее количество компиляторов. Также Вам может понадобиться столкнуться с периодом — до variadic templates.

Б>
Б>namespace hl = std;
Б>template <template <typename... > class Tmp> struct holder {};

Б>template <typename T> struct extract : hl::false_type {};

Б>template <typename... Ts, template <typename... > class Tmpl>
Б>struct extract<Tmpl<Ts...>> : hl::true_type
Б>{
Б>    typedef holder<Tmpl> type;
Б>};
 
Б>int main()
Б>{
Б>  enum {v = std::is_same<typename extract<T>::type, holder<std::set>>::value};
Б>}
Б>


Ну и кроме того, давай, ты сначала доведешь своей пример до компилируемого состояния, покажешь пример использования в контесте задачи, а потом я расскажу, почему это плохо. Договорились?

А то ведь знаешь как бывает, идея кажется правильной, пока не компилируется. А как начинаешь доводить до компиляции оказывается, что сама идея никуда не годится и нужно придумывать что-то другое.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 11.02.2023 11:52 rg45 . Предыдущая версия . Еще …
Отредактировано 11.02.2023 11:48 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 11:26 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 11:24 rg45 . Предыдущая версия .
Re[9]: Философско-практические вопросы про метапрограммирова
От: ботаныч Интернет https://youtube.com/shorts/eapWB7W8hEE
Дата: 11.02.23 15:05
Оценка:
Здравствуйте, rg45, Вы писали:

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


М>>>А можете, если есть время, более подробно написать

Б>> почитав код ниже, мне хочется вопрос задать. Вам это в каком контексте надо? Если для продакшин кода, то специфика одна, если для библиотечного кода, да еще и header only подход будет сршенно разным, для нового продакшин кода, подход rg45 достаточно лаконичен, где стандарт и набор компиляторов практически предопределен и меняется довольно редко (хотя и там будут вопросы по скорости компиляции, иногда короткие лаконичные вещи компилируются дольше). Если же это библиотечный код, то часто предпочтение отдается дедовским версиям SFINAE громоздким, но покрывающим большее количество компиляторов. Также Вам может понадобиться столкнуться с периодом — до variadic templates.

М>>>UPD

М>>>Еще, наверно, можно попробовать оттолкнуться от std::is_same_v<T, std::set>
Б>>
Б>>namespace hl = std;
Б>>template <template <typename... > class Tmp> struct holder {};

Б>>template <typename T> struct extract : hl::false_type {};

Б>>template <typename... Ts, template <typename... > class Tmpl>
Б>>struct extract<Tmpl<Ts...>> : hl::true_type
Б>>{
Б>>    typedef holder<Tmpl> type;
Б>>};
 
Б>>int main()
Б>>{
Б>>  enum {v = std::is_same<typename extract<T>::type, holder<std::set>>::value};
Б>>}
Б>>


R>И как потом с этим подходом можно будет расширять правила для пользовательских типов, находящихся в клиенстких простраствах имен? Например, как можно(нужно) переписать вот этот фрагмент:

что ты что ты )) это прсто is_same — там в is_same set вставлен, я показал как можно сверить шаблон, ..вроде компилируется. не заметил ниже is_instance
это не сфинай для проверки наличия sort. sort сфиная проверка метода из олдовых SFINAE выглядит чуточку массивнее

R>А просадка времени компиляции откуда возьмется (по сравнению с твоим вариантом)? Объявления функций все просадят что ли?

а я не замерял, можно проверить кстати в сравнеии с олдовым SFINAE для проверки сорта с более свезжим способами. Я замечал, что тупая итерация типов в тупле гораздо дольше компилируется, чем если проделать это вручную через template <typename ...Ts> struct types;
вообще, по правде говоря встретив твой способ, воспользовался бы им, Но когда мне такое надобилось, не было таких способов, писалось классическим способом
Re[9]: Философско-практические вопросы про метапрограммирова
От: ботаныч Интернет https://youtube.com/shorts/eapWB7W8hEE
Дата: 11.02.23 15:07
Оценка:
Здравствуйте, rg45, Вы писали:

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


Б>>Здравствуйте, Максим, Вы писали:


М>>>А можете, если есть время, более подробно написать

Б>> почитав код ниже, мне хочется вопрос задать. Вам это в каком контексте надо? Если для продакшин кода, то специфика одна, если для библиотечного кода, да еще и header only подход будет сршенно разным, для нового продакшин кода, подход rg45 достаточно лаконичен, где стандарт и набор компиляторов практически предопределен и меняется довольно редко (хотя и там будут вопросы по скорости компиляции, иногда короткие лаконичные вещи компилируются дольше). Если же это библиотечный код, то часто предпочтение отдается дедовским версиям SFINAE громоздким, но покрывающим большее количество компиляторов. Также Вам может понадобиться столкнуться с периодом — до variadic templates.

Б>>
Б>>namespace hl = std;
Б>>template <template <typename... > class Tmp> struct holder {};

Б>>template <typename T> struct extract : hl::false_type {};

Б>>template <typename... Ts, template <typename... > class Tmpl>
Б>>struct extract<Tmpl<Ts...>> : hl::true_type
Б>>{
Б>>    typedef holder<Tmpl> type;
Б>>};
 
Б>>int main()
Б>>{
Б>>  enum {v = std::is_same<typename extract<T>::type, holder<std::set>>::value};
Б>>}
Б>>


R>Ну и кроме того, давай, ты сначала доведешь своей пример до компилируемого состояния, покажешь пример использования в контесте задачи, а потом я расскажу, почему это плохо. Договорились?


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

https://onlinegdb.com/4hmabsGci
да вот же, я же говорю, это просто проверка на инстанс сета ))
Re[10]: Философско-практические вопросы про метапрограммиров
От: rg45 СССР  
Дата: 11.02.23 15:49
Оценка:
Здравствуйте, ботаныч, Вы писали:

Б>https://onlinegdb.com/4hmabsGci

Б>да вот же, я же говорю, это просто проверка на инстанс сета ))

А для чего нам это проверка нужна вообще? Эта утилита родилась же в контексте нашей синтетической задачи, правда? Вот и попробуй применить свой подход при решении задачи: http://coliru.stacked-crooked.com/a/fdbaf2f292d21344. Только не умозрительно, а чтоб работало. Потом сравним. Обрати внимание, пример немного изменен — добавлены пространства имен, как это обычно бывает в реальной жизни.

P.S. Единственный плюс такого подхода в том, что он позволит перечислить все стандартные контейнеры в одной специализации. Но плюс достаточно сомнительный, как по мне, если учесть, что этой для того, чтобы эта монолитная специализация стала возможна, сперва нужно определить несколько дополнительных сущщностей, не слишком удобочитаемых. А в случаях, когда предполагается расширение специализаций для пользовательских типов, разбросанных по разным пространствам имен, использование этого подхода крайне неудобно и порождает в местах специализаций нагромождения кода, которые ужасно будут раздражать при первом же рефакторинге. Нагромождения связаны в первую очередь необходимостью разрывать пользовательские пространства имен для выполнения специализаций библиотечного класса. И, чем больше таких мест, тем более ужасная картина будет получаться. Вынос этих специализаций в какое-то отдельное место также имее свои ощутимые недостатки.

Вот видоизмененный пример, на котором можно прочувствовать проблему, о которой я говорю. Центральное место здесь занимает пользовательский класс MySortedContainer, который должен обрабатыватся по тем же правилам, что и отсортированные стандартные контейнеры (map, set и пр.).

http://coliru.stacked-crooked.com/a/fdbaf2f292d21344.

#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <utility>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Generic Library Area

namespace lib
{

template <typename, typename = void>
struct has_sort_member_function : std::false_type {};

template <typename T>
struct has_sort_member_function<T, std::void_t<decltype(std::declval<T&>().sort())>> : std::true_type {};

template <typename, typename = void>
struct is_std_sort_applicable : std::false_type{};

template <typename T>
struct is_std_sort_applicable<T, std::void_t<
   decltype(std::sort(std::begin(std::declval<T&>()), std::end(std::declval<T&>()))),
   decltype(*std::begin(std::declval<T&>()) = *std::begin(std::declval<T&>()))
>> : std::true_type {};

template <typename T>
auto assume_sorted_range(const T&) -> std::false_type;

// For standard containers, the traits must be defined beforehand
template <typename K, typename T, typename C, typename A>
auto assume_sorted_range(const std::map<K, T, C, A>&) -> std::true_type;

template <typename K, typename T, typename C, typename A>
auto assume_sorted_range(const std::multimap<K, T, C, A>&) -> std::true_type;

template <typename T, typename C, typename A>
auto assume_sorted_range(const std::set<T, C, A>&) -> std::true_type;

template <typename T, typename C, typename A>
auto assume_sorted_range(const std::multiset<T, C, A>&) -> std::true_type;

template <typename T>
using is_sorted_container = decltype(assume_sorted_range(std::declval<T>()));

template <typename T, std::enable_if_t<has_sort_member_function<T>::value, int> = 0>
void sort(T& t)
{
   t.sort();
}

template <typename T, std::enable_if_t<
   is_std_sort_applicable<T>::value &&
   !has_sort_member_function<T>::value &&
   !is_sorted_container<T>::value,
int> = 0>
void sort(T& t)
{
   std::sort(std::begin(t), std::end(t));
}

template <typename T, std::enable_if_t<
   is_sorted_container<T>::value &&
   !has_sort_member_function<T>::value,
int> = 0>
void sort(const T&)
{
   // Container is sorted already, so nothing to do.
}

} // namespace lib


namespace app1 {
namespace app2 {
namespace app3 {    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Custom Application Area

class MySortedContainer
{
public:

    auto begin() const { return m.begin(); }
    auto end() const { return m.end(); }

    void add_element(int key, int value) { m.emplace(key, value); }

private:
    std::map<int, int> m;
};
auto assume_sorted_range(const MySortedContainer&) -> std::true_type;

struct MyContainer
{
   void sort() { std::cout << "MyContainer::sort" << std::endl; }
};

void test()
{
   std::string string = "Hello World!";
   lib::sort(string);
   std::cout << "<" << string << ">" << std::endl;

   int array[] { 3, 5, 2, 9, 1, 7, 4, 8, 0, 6 };
   lib::sort(array);

   std::vector<int> vector { 3, 5, 2, 9, 1, 7, 4, 8, 0, 6 };
   lib::sort(vector);

   std::set<int> set { 3, 5, 2, 9, 1, 7, 4, 8, 0, 6 };
   lib::sort(set); // no effect

   MyContainer my_container;
   lib::sort(my_container);

   MySortedContainer my_sorted_container;
   lib::sort(my_sorted_container); // no effect

   char str[] = "Hello World!";
   lib::sort(str); // Ok
   // lib::sort("Hello World!"); // error: no matching function for call
}

} // namespace app3
} // namespace app2
} // namespace app1

int main()
{
    app1::app2::app3::test();
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 11.02.2023 17:05 rg45 . Предыдущая версия . Еще …
Отредактировано 11.02.2023 17:04 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 17:03 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:57 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:56 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:50 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:49 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:44 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:40 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:18 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:14 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:12 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:08 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:05 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 16:02 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 15:55 rg45 . Предыдущая версия .
Re[11]: Философско-практические вопросы про метапрограммиров
От: ботаныч Интернет https://youtube.com/shorts/eapWB7W8hEE
Дата: 11.02.23 17:04
Оценка:
Здравствуйте, rg45, Вы писали:

R>Зачем нам эта проверка?

это был ответ на

оттолкнуться от std::is_same_v<T, std::set>

я просто показал, что параметром шаблона неспециализированный шаблон низя, но сравнить можно — вот так, и ..там мало кода.
я не говорил, что тут проверка на наличие метода sort. даже, что пример к этому относится относится
Re[12]: Философско-практические вопросы про метапрограммиров
От: rg45 СССР  
Дата: 11.02.23 17:11
Оценка:
Здравствуйте, ботаныч, Вы писали:

R>>Зачем нам эта проверка?

Б>это был ответ на
Б>

Б>оттолкнуться от std::is_same_v<T, std::set>

Б>я просто показал, что параметром шаблона неспециализированный шаблон низя, но сравнить можно — вот так, и ..там мало кода.
Б>я не говорил, что тут проверка на наличие метода sort. даже, что пример к этому относится относится

Ты говорил о предложенном мной подходе:

http://rsdn.org/forum/cpp/8467966.1
Автор: ботаныч
Дата: 11.02.23


для нового продакшин кода, подход rg45 достаточно лаконичен, где стандарт и набор компиляторов практически предопределен и меняется довольно редко (хотя и там будут вопросы по скорости компиляции, иногда короткие лаконичные вещи компилируются дольше). Если же это библиотечный код, то часто предпочтение отдается дедовским версиям SFINAE громоздким, но покрывающим большее количество компиляторов.


Как я понял, ты предлагаешь другой подход, который лучше. И мне трудно понять, на чем основываются твои выводы о скорости компиляции и о количестве доступных компиляторов. По-моему, твое решение проблемнее по обоим перечисленным аспектам. Мой подход основывается на простых объявлениях перегруженных функций, что может быть проще?. Или я неправильно тебя понял?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 11.02.2023 17:21 rg45 . Предыдущая версия . Еще …
Отредактировано 11.02.2023 17:19 rg45 . Предыдущая версия .
Re[12]: Философско-практические вопросы про метапрограммиров
От: rg45 СССР  
Дата: 11.02.23 17:36
Оценка:
Здравствуйте, ботаныч, Вы писали:

Б>я просто показал, что параметром шаблона неспециализированный шаблон низя, но сравнить можно — вот так, и ..там мало кода.


Нифига себе мало кода. Его мало, потому что ты не довел его до логического завершения. А ты доведи его хотя бы до определения метафункции и сравни:

  Мой вариант
// For standard containers, the traits must be defined beforehand
template <typename K, typename T, typename C, typename A>
auto assume_sorted_range(const std::map<K, T, C, A>&) -> std::true_type;

template <typename K, typename T, typename C, typename A>
auto assume_sorted_range(const std::multimap<K, T, C, A>&) -> std::true_type;

template <typename T, typename C, typename A>
auto assume_sorted_range(const std::set<T, C, A>&) -> std::true_type;

template <typename T, typename C, typename A>
auto assume_sorted_range(const std::multiset<T, C, A>&) -> std::true_type;

template <typename T>
using is_sorted_container = decltype(assume_sorted_range(std::declval<T>()));

  Твой вариант
namespace hl = std;

template <template <typename... > class Tmp> struct holder {};

template <typename T> struct extract : hl::false_type {};

template <typename... Ts, template <typename... > class Tmpl>
struct extract<Tmpl<Ts...>> : hl::true_type
{
    typedef holder<Tmpl> type;
};

template <typename, typename = void>
struct is_sorted_container : std::false_type {};

template <typename T>
struct is_sorted_container<T, std::enable_if_t<
    std::is_same<typename extract<T>::type, holder<std::set>>::value ||
    std::is_same<typename extract<T>::type, holder<std::map>>::value ||
    std::is_same<typename extract<T>::type, holder<std::multimap>>::value ||
    std::is_same<typename extract<T>::type, holder<std::multiset>>::value
>> : std::true_type {};


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

А еще поставь себя на место нового сотрудника, который недавно пришел и разбирается с исходниками компании. Какой вариант легче для понимания?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 11.02.2023 18:12 rg45 . Предыдущая версия . Еще …
Отредактировано 11.02.2023 18:11 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 18:02 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 17:57 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 17:52 rg45 . Предыдущая версия .
Отредактировано 11.02.2023 17:40 rg45 . Предыдущая версия .
Re[13]: Философско-практические вопросы про метапрограммиров
От: ботаныч Интернет https://youtube.com/shorts/eapWB7W8hEE
Дата: 11.02.23 18:32
Оценка:
Здравствуйте, rg45, Вы писали:

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


R>>>Зачем нам эта проверка?

Б>>это был ответ на
Б>>

Б>>оттолкнуться от std::is_same_v<T, std::set>

Б>>я просто показал, что параметром шаблона неспециализированный шаблон низя, но сравнить можно — вот так, и ..там мало кода.
Б>>я не говорил, что тут проверка на наличие метода sort. даже, что пример к этому относится относится

R>Ты говорил о предложенном мной подходе:


R>http://rsdn.org/forum/cpp/8467966.1
Автор: ботаныч
Дата: 11.02.23


R>

R>для нового продакшин кода, подход rg45 достаточно лаконичен, где стандарт и набор компиляторов практически предопределен и меняется довольно редко (хотя и там будут вопросы по скорости компиляции, иногда короткие лаконичные вещи компилируются дольше). Если же это библиотечный код, то часто предпочтение отдается дедовским версиям SFINAE громоздким, но покрывающим большее количество компиляторов.


R>Как я понял, ты предлагаешь другой подход, который лучше.

нет. я сказал, что есть практики основанные на олдовых SFINAE для определения наличия методов. просто из своего опыта. из этой-же причине я предположил, что эти две разные имплементации могут компилироваться с разной скоростью.

R>И мне трудно понять, на чем основываются твои выводы о скорости компиляции и о количестве доступных компиляторов. По-моему, твое решение проблемнее по обоим перечисленным аспектам. Мой подход основывается на простых объявлениях перегруженных функций, что может быть проще?. Или я неправильно тебя понял?

свои предположения я строю опять-же на практике. я упоминал прецедент с туплом и тривиальным вариэдиком.

я не считаю один солюшин лучше, другой хуже. просто описал свои соображения. единственно что )) так это я не уверен, что смогу заставить себя тащить "свой" (он не мой) вариант.
Re[3]: Философско-практические вопросы про метапрограммирование
От: cppguard  
Дата: 12.02.23 16:09
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

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


C>> пусть твои сомнения развеют Торвальдс и Беллар. Один написал классную операционку, а второй делает потрясающие проекты в одиночку. И оба не пишут на С++.


BFE>А вы пробовали читать их код?


Код Торвальдся вполне читаем. У Беллара — write-only (я читал код tcc).
Re[9]: Философско-практические вопросы про метапрограммирова
От: _NN_ www.nemerleweb.com
Дата: 16.02.23 06:21
Оценка: +1
Здравствуйте, sergii.p, Вы писали:

SP>
SP>template <typename, template <typename...> typename>
SP>struct is_instance : std::false_type {};

SP>template <typename T, template <typename...> typename U>
SP>struct is_instance<U<T>, U> : std::true_type {};

SP>template <typename T>
SP>using is_sorted_container = std::bool_constant<is_instance<T, std::set>::value
SP>                                            && is_instance<T, std::map>::value
SP>                                            && is_instance<T, std::multi_map>::value
SP>                                            && is_instance<T, std::multi_set>::value>;
SP>


Так делать не стоит.
Дело в том, что операции && и || в этом контексте вынудят компилятор инстанциировать все варианты is_instance, а потом только произвести операцию «И», «ИЛИ».

Здесь нужно использовать std::conjuction, std::disjunction.

Или концепты где && и || будут означать std::conjuction, std::disjunction.

https://en.cppreference.com/w/cpp/types/conjunction
https://en.cppreference.com/w/cpp/types/disjunction
http://rsdn.nemerleweb.com
http://nemerleweb.com
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.