Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.156] |
|
|
Правила раздела:
| Страницы: (495) « Первая ... 345 346 [347] 348 349 ... 494 495 ( Перейти к последнему сообщению ) |
Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
|
Сообщ.
#5191
,
|
|
|
|
korvin, а помнишь, я тебе map для списка типов показывал. Там тоже некорректное сравнение
? Добавлено Во, нашел: Цитата D_KEY @ Цитата давай рассмотрим реализацию map ![]() ![]() map fn [] = [] map fn (x:xs) = fn x : map fn xs как это будет выглядеть в C++? Во время компиляции? Как-то так: Сначала списки: ![]() ![]() template< typename H, typename T > struct List { typedef H head; typedef T tail; }; struct NullType {}; Теперь map: ![]() ![]() template< template<typename T> class Fn, typename Lst > struct Map; // map fn [] = [] template< template<typename T> class Fn > struct Map<Fn, NullType> { typedef NullType result; }; // map fn (x:xs) = fn x : map fn xs template< template<typename T> class Fn, typename X, typename Xs > struct Map<Fn, List<X, Xs> > { typedef List < typename Fn<X>::result, typename Map<Fn, Xs>::result > result; }; Я имел в виду как раз сходство механизма, а не способа применения. В рантайме в С++ сопоставления с образцом нет(но реализовать можно). |
|
Сообщ.
#5192
,
|
|
|
|
1) образцы проверяются по-порядку их определения, т.к. в общем случае невозможно автоматически выстроить линейный приоритет, поэтому следующий код в Хаскелле работает ![]() ![]() data Type = Type { name :: String } deriving (Show, Eq, Read) a :: Type -> Type -> String a (Type "T") _ = "a T _" a _ (Type "T") = "a _ T" a _ _ = "a _ _" test = a (Type "T") (Type "T") ![]() ![]() *Main> test "a T _" *Main> а аналогичный в C++ ![]() ![]() #include <iostream> template<class t1, class t2> class A { public: void foo() { std::cout << "A<*, *>.foo();" << std::endl; } }; class T {}; template<class t> class A<T, t> { public: void foo() { std::cout << "A<T, *>.foo();" << std::endl; } }; template<class t> class A<t, T> { public: void foo() { std::cout << "A<*, T>.foo();" << std::endl; } }; int main() { A<T, T> aTT; aTT.foo(); return 0; } нет ![]() ![]() $ g++ -o test test.cpp test.cpp: In function ‘int main()’: test.cpp:39: error: ambiguous class template instantiation for ‘class A<T, T>’ test.cpp:15: error: candidates are: class A<T, t> test.cpp:23: error: class A<t, T> test.cpp:39: error: aggregate ‘A<T, T> aTT’ has incomplete type and cannot be defined $ 2) дефолтный образец (в данном случае a _ _) определяется последним, иначе выполняться будет только он 3) нельзя определить новый образец, т.к. фактически запись ![]() ![]() a :: Type -> Type -> String a (Type "T") _ = "a T _" a _ (Type "T") = "a _ T" a _ _ = "a _ _" является синтаксическим сахаром для ![]() ![]() a :: Type -> Type -> String a t1 t2 = case (t1, t2) of (Type "T", _ ) -> "a T _" (_, Type "T") -> "a _ T" (_, _ ) -> "a _ _" собственно так ведет себя pattern-matching везде, где я видел (Haskell, OCaml, Racket, CL) и, думаю многие другие языки, где он есть -- не исключение. |
|
Сообщ.
#5193
,
|
|
|
|
Цитата korvin @ И что в этом хорошего? Поведение программы зависит от порядка строк? Скопипастил и получил по лбу? Плюсы же явно показывают равноправие обоих специализаций. образцы проверяются по-порядку их определения, |
|
Сообщ.
#5194
,
|
|
|
|
korvin, так я и не говорил, что это одно и тоже, я тебе объяснял работу шаблонов на более понятном, как я надеялся, тебе языке.
Шаблоны для данного случая работают именно так, как я сказал: Цитата D_KEY @ ![]() ![]() basic_string :: type -> type -> type -> type В "реализации" все специализации - паттерны для pattern-matching'а, как и наличие обсуждаемых "опциональных" частей. А "обычная" реализация - это _ У тебя есть возражения по сути разговора-то? По шаблонам и дженерикам, по опциональным возможностям и т.п.? Добавлено Цитата Qraizer @ Плюсы же явно показывают равноправие обоих специализаций. Qraizer, там уже динамика. И такой порядок соответствует нашему switch или блокам catch. |
|
Сообщ.
#5195
,
|
|
|
|
Цитата D_KEY @ korvin, а помнишь, я тебе map для списка типов показывал. Там тоже некорректное сравнение ?ты мне покажи использование теперь, что с этим можно сделать. |
|
Сообщ.
#5196
,
|
|
|
|
Цитата korvin @ 2) дефолтный образец (в данном случае a _ _) определяется последним, иначе выполняться будет только он Ну, кстати, дефолтный шаблон тоже можно определить последним. Вот объявить - да, первым. |
|
Сообщ.
#5197
,
|
|
|
|
Цитата korvin @ Цитата D_KEY @ korvin, а помнишь, я тебе map для списка типов показывал. Там тоже некорректное сравнение ?ты мне покажи использование теперь, что с этим можно сделать. Манипулировать списками типов, как я тебе раньше и писал: Цитата D_KEY @ korvin, пример использования: ![]() ![]() // "функция" template<typename T> struct Test { typedef std::vector<T> result; }; // список типов: typedef List<int, List<double, List<std::string, NullType> > > MyList; // с помощью map "создаем" новый список типов из существующего: typedef Map<Test, MyList>::result MyVecList; // результат будет таким: // List<std::vector<int>, List<std::vector<double>, List<std::vector<std::string>, NullType> > > Т.е. из списка int, doube, string мы получим список vector<int>, vector<double>, vector<string> А дальше - создавать типы, с помощью всего этого |
|
Сообщ.
#5198
,
|
|
|
|
Цитата Qraizer @ И что в этом хорошего? Поведение программы зависит от порядка строк? Скопипастил и получил по лбу? Плюсы же явно показывают равноправие обоих специализаций. что скопипастил и почему получил по лбу? Добавлено Цитата D_KEY @ Манипулировать списками типов, как я тебе раньше и писал: Цитата D_KEY @ korvin, пример использования: ![]() ![]() // "функция" template<typename T> struct Test { typedef std::vector<T> result; }; // список типов: typedef List<int, List<double, List<std::string, NullType> > > MyList; // с помощью map "создаем" новый список типов из существующего: typedef Map<Test, MyList>::result MyVecList; // результат будет таким: // List<std::vector<int>, List<std::vector<double>, List<std::vector<std::string>, NullType> > > Т.е. из списка int, doube, string мы получим список vector<int>, vector<double>, vector<string> А дальше - создавать типы, с помощью всего этого ![]() ага, т.е. если мы теперь определим у себя ![]() ![]() // ну тут примерно, проверять и доводить до рабочего состояния сейчас лень class T {}; template< template<typename T> class Fn, typename X, typename Xs > struct Map<Fn, T> { typedef List < typename Fn<NullType>::result, typename Map<Fn, NullType>::result > result; }; то поломаем нафик весь Map? |
|
Сообщ.
#5199
,
|
|
|
|
Цитата korvin @ ага, т.е. если мы теперь определим у себя ![]() ![]() Не заметил определение класса T. Мы не сломаем Map, а сделаем нужную(раз сделали) для нас специализацию. Цитата то поломаем нафик весь Map? Если мы у себя на компьютере отформатируем жесткий диск, то все файлы пропадут. |
|
Сообщ.
#5200
,
|
|
|
|
Цитата MyNameIsIgor @ Ну, кстати, дефолтный шаблон тоже можно определить последним. Вот объявить - да, первым. не суть, я к тому, что в шаблонах наиболее общий шаблон выполняется только если ни один другой не подошел, независимо от порядка их определения, в то время как в сопоставлении образцов он выполняется только если ни один из предыдущих не подошел. т.е. в случае образцов мы рискуем никогда не дойти до какой-то ветки (но это хаскелл по крайней мере (почти) всегда выявляет при компиляции), а в случае шаблонов мы не можем ничего утверждать наверняка, глядя только на авторское определение, нам нужно видеть также все их "перегрузки". Qraizer, в случае паттерн-матчинга эти определения не равноправны, т.к. первый выполняется при (t1.name == "T"), а второй -- при (t1.name != "T" && t2.name == "T") |
|
Сообщ.
#5201
,
|
|
|
|
Цитата korvin @ а в случае шаблонов мы не можем ничего утверждать наверняка глядя только на авторское определение, нам нужно видеть так же все их "перегрузки". Ну, извиняюсь, специализации мы либо написали сами, либо сами же подключили. Так же, как сами подключили первоначальное объявление шаблона (не обязательно определение). |
|
Сообщ.
#5202
,
|
|
|
|
Цитата D_KEY @ Мы не сломаем Map, а сделаем нужную(раз сделали) для нас специализацию. именно, что сломаем, т.к. для нашего типа Map будет вести себя не так, как изначально предполагалось. Цитата D_KEY @ Если мы у себя на компьютере отформатируем жесткий диск, то все файлы пропадут. отличное оправдание, а теперь попробуй таким же образом сломать хаскелловый map так что да, сравнение некорректное |
|
Сообщ.
#5203
,
|
|
|
|
Цитата korvin @ а в случае шаблонов мы не можем ничего утверждать наверняка, глядя только на авторское определение, нам нужно видеть также все их "перегрузки". Да, в этом одно из ключевых отличий. В случае шаблонов возможность их специализации является частью их интерфейса. Но тут играет специфика того, что мы работаем с типами, а для них это логично: ![]() ![]() template<typename T> class SomeTraits { // Дефолтная дженерик-реализация для указанного типа // ... }; template<typename T, template<typename T> class Traits> class SomeClass { //... // Используем Traits<T> и Traits<какой-либо тип> //... }; Мы можем, как передавать свой класс-шаблон характеристик в SomeClass, так и специализировать SomeTraits только для нужного нам типа. Добавлено Цитата korvin @ Цитата D_KEY @ Мы не сломаем Map, а сделаем нужную(раз сделали) для нас специализацию. именно, что сломаем, т.к. для нашего типа Map будет вести себя не так, как изначально предполагалось. Тогда зачем мы делали эту специализацию ?Цитата Цитата D_KEY @ Если мы у себя на компьютере отформатируем жесткий диск, то все файлы пропадут. отличное оправдание, а теперь попробуй таким же образом сломать хаскелловый map ![]() ![]() my_map fn x:<какое-то конкретное значение> = [] my_map fn other = map fn other Добавлено Цитата korvin @ так что да, сравнение некорректное В зависимости от контекста такого сравнения. В обсуждаемом случае - различия не важны. |
|
Сообщ.
#5204
,
|
|
|
|
Цитата MyNameIsIgor @ либо сами же подключили. это же могло произойти и неявно |
|
Сообщ.
#5205
,
|
|
|
|
Цитата korvin @ Цитата MyNameIsIgor @ либо сами же подключили. это же могло произойти и неявно Как? |