
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.217.4] |
![]() |
|
Страницы: (33) « Первая ... 8 9 [10] 11 12 ... 32 33 ( Перейти к последнему сообщению ) |
Сообщ.
#136
,
|
|
|
Какой-то детский сад. Я-то думал, что тебе есть, что сказать, мало ли, вдруг чего-то не знаю.
Иначе проще будет забить и позволить компилятору ругаться в месте применения переданной функции, чем городить огород имеющими средствами. В крайнем случае, воткнуть static_assert с использованием boost::function_traits (и да, я в курсе, что там тоже SFINAE внутри). Ну и я уже нашёл, что в D оно таки есть из коробки - arity, ReturnType, ParameterTypeTuple и т.д. Собственно, что хотел сказать - в С++ у нас или такие костыли (справедливости ради, они не особо часто и нужны) или std::function с лишним выделением памяти. В расте мало того, что оно делается легко, так что ещё и выглядит почти одинаково: ![]() ![]() fn test_static<T: Fn(i32) -> i32>(f: T) { println!("{}", f(10)); } fn test_dynamic(f: &Fn(i32) -> i32) { println!("{}", f(20)); } fn foo(a: i32) -> i32 { a + 10 } fn main() { test_static(foo); test_dynamic(&foo); } |
Сообщ.
#137
,
|
|
|
Я правильно понимаю? Нам потребуется отдельный трейт для каждого сериализуемого типа? То есть в D я просто создал структуру и вызвал serialize. А в Rust для каждой сериализуемой структуры придется городить свой кастомный трейт?
|
Сообщ.
#138
,
|
|
|
Цитата DarkEld3r @ Какой-то детский сад. Т.е. вас только в детском саду просили отвечать за свои слова? Цитата DarkEld3r @ Я-то думал, что тебе есть, что сказать Возможно есть, возможно - нет. В любом случае я хочу, чтобы слушающий обладал достаточным интеллектом, чтобы понять сказанное. Цитата DarkEld3r @ мало ли, вдруг чего-то не знаю Не знаете. Начните заполнять прорехи в вашем образовании с понятия "интерфейс". Цитата DarkEld3r @ воткнуть static_assert Это правильное решение, если не требуется перегрузка по сигнатуре функции. Ах, да, в Rust же перегрузки нет ![]() Цитата DarkEld3r @ с использованием boost::function_traits Не нужно, ибо не переварит перегрузку operator(). Цитата DarkEld3r @ и да, я в курсе, что там тоже SFINAE внутри Кто подсказал? |
Сообщ.
#139
,
|
|
|
Почти. Классы и указатели на структуры точно не могут.
Цитата DarkEld3r @ Присвоить результат функции глобальной или статической const/immutable переменной, передать результат в качестве параметра шаблона, вызвать эту функцию внутри шаблона в процессе инстанцирования. Ну и раз, "по разному", то может ещё пару вариантов приведёшь? A то бегло не нагуглить не удалось. Добавлено Цитата DarkEld3r @ В D для такого примитива не нужны ни arity ни ReturnType ни ParameterTypeTuple:Ну и я уже нашёл, что в D оно таки есть из коробки - arity, ReturnType, ParameterTypeTuple и т.д. Собственно, что хотел сказать - в С++ у нас или такие костыли (справедливости ради, они не особо часто и нужны) или std::function с лишним выделением памяти. В расте мало того, что оно делается легко, так что ещё и выглядит почти одинаково: http://dpaste.dzfl.pl/6e83bb30275a ![]() ![]() import std.stdio; void test_static(T: int function(int))(T foo) { foo(10).writeln; } void test_dynamic(int function(int) foo) { foo(20).writeln; } int foo(int a) { return a + 10; } void main() { test_static(&foo); test_dynamic(&foo); } |
Сообщ.
#140
,
|
|
|
Цитата applegame @ Да, придётся. Я правильно понимаю? Нам потребуется отдельный трейт для каждого сериализуемого типа? То есть в D я просто создал структуру и вызвал serialize. Правильно я понимаю, что в D для структур ты будешь сериализовать все члены? В общем случае, это ведь некорректно. С тем, что удобнее иметь такое поведение по умолчанию с возможностью запретить сериализацию отдельных полей спорить не буду. Наверняка, можно сделать подобное на макросах и в расте, но сейчас пример набросать не готов. Цитата MyNameIsIgor @ Газификация луж продолжается. Начните заполнять прорехи в вашем образовании с понятия "интерфейс". Добавлено Цитата applegame @ Ок, спасибо. Второй вариант - это просто указатель на функцию или аналог плюсового std::function? Если первое, то немного не то.В D для такого примитива не нужны ни arity ни ReturnType ни ParameterTypeTuple: А вот с шаблоном интересно, жаль в С++ так нельзя. |
Сообщ.
#141
,
|
|
|
А вот для ситуации, когда функция должна принять любой callable тип c заданными параметрами, а не только собственно функцию, эти трейты пригодятся:
http://dpaste.dzfl.pl/2d66a35eff90 ![]() ![]() import std.stdio; import std.traits; import std.typetuple; void test(T)(T foo) if( isCallable!T && is(ReturnType!T == int) && is(ParameterTypeTuple!T == TypeTuple!int) ) { foo(10).writeln; } int foo(int a) { return a + 10; } struct Bar { int opCall(int a) { return a + 20; } } int baz(short a) { return a + 30; } void main() { test(&foo); Bar bar; test(bar); // test(&baz); // fail } Rust так умеет? В C++ кстати это тоже возможно, правда несколько сложнее. Добавлено Цитата DarkEld3r @ Это указатель, а в Rust это что? В D аналог std::function не нужен, его заменяют лямбды (а точнее делегаты), которые, в отличие от C++, имеют четко описанный тип зависящий только от параметров и возвращаемого значения. Ок, спасибо. Второй вариант - это просто указатель на функцию или аналог плюсового std::function? Если первое, то немного не то. Добавлено Цитата DarkEld3r @ Не обязательно все. В D можно еще указывать user defined attributes, которые также возможно читать compile-time. С помощью них можно задавать всякие флажки. Типа:Правильно я понимаю, что в D для структур ты будешь сериализовать все члены? В общем случае, это ведь некорректно. С тем, что удобнее иметь такое поведение по умолчанию с возможностью запретить сериализацию отдельных полей спорить не буду. ![]() ![]() struct Data { int field; @ignored { string ignoredString; int ignoredInt; } @name("zoo") short _un_readableNamed_; } |
Сообщ.
#142
,
|
|
|
Цитата applegame @ "Теоретически". Выше в примерах кода (Fn(i32) -> i32), Fn - это как раз трейт. Их есть три вида: Fn, FnMut и FnOnce. Лямбды - это как раз сахар для этих трейтов. Для своего типа этот трейты, по идее, тоже можно реализовать, но сейчас это "нестабильная фича". Попробовал набросать пример, для этого надо "переключаться" на "ночной" раст - в стабильных реализах нестабильные вещи использовать запрещено. Получил "internal compiler error" и предложение отправить баг-репорт. Rust так умеет? ![]() Цитата applegame @ "Трейт-обьект", по сути - это как раз аналог std::function. Ну или той обёртки, что ты делал когда демонстрировал добавление реализации интерфейса.Это указатель, а в Rust это что? Цитата applegame @ В расте у callable сущностей тоже один тип - Fn/FnMut/FnOnce (в зависимости от сигнатуры). Вне зависимости от того лямбда это, функция или тип с вручную реализованными нужными трейтами.его заменяют лямбды (а точнее делегаты), которые, в отличие от C++, имеют четко описанный тип зависящий только от параметров и возвращаемого значения. Что это будет в итоге - зависит от использования. Если дженерик, то заинлайнится. Если ссылка/указатель на трейт - то будет "обёртка". Цитата applegame @ В расте, "пока что", нельзя (есть сколько-то готовых), но планы добавить свои есть.В D можно еще указывать user defined attributes Кстати, любопытно - как в D разруливаются конфликты имён в атрибутах? Цитата applegame @ Но в чужой тип их ведь не впихнёшь? С помощью них можно задавать всякие флажки. |
Сообщ.
#143
,
|
|
|
Цитата DarkEld3r @ В смысле не впихнешь? В D UDA - это либо произвольный тип, либо значение.Но в чужой тип их ведь не впихнёшь? ![]() ![]() struct MySuperAttribute { int a; } enum attr1 = MySuperAttribute(2); enum attr2 = MySuperAttribute(3); alias attr3 = MySuperAttribute; struct Bar { } struct Foo { @attr1 int f1; @attr2 int f2; @attr3 int f3; @attr3(2) int f4; @Bar int f5; @("string", 10, Bar) int f6; // несколько атрибутов } Цитата DarkEld3r @ Кстати, любопытно - как в D разруливаются конфликты имён в атрибутах? Решаются также, как конфликты имен типов. |
![]() |
Сообщ.
#144
,
|
|
Цитата applegame @ В целом да. Явно этого не говорится, однако это следует из некоторых пунктов, описывающих лэйаут структур – конечно же она там C-совместимая – и определения наследования. Однако не всегда. Исключения позволяются при виртуальном наследовании и если потомок "вдруг" становится полиморфным. Также из описания объектной модели (не путать с описанием модели ООП!) следует ещё одна возможность исключения, когда базовые классы имеют "нулевой" размер. Стандарт C++ разве требует чтобы потомок имел тот же размер, что и предок, в случаях когда не добавляются дополнительные данные? Добавлено Цитата MyNameIsIgor @ Лично я в этой фразедаже не во всех словах разобрался, так что смысл фразы расплылся где-то на километр. Куда уж мне с тобой спорить было бы. В любом случае я хочу, чтобы слушающий обладал достаточным интеллектом, чтобы понять сказанное. |
Сообщ.
#145
,
|
|
|
Цитата applegame @ Ну в примере кода ты объявляешь структуру Data с ignored внутри. Если дата уже где-то определена, то так не получится?В смысле не впихнешь? Цитата applegame @ То есть UDA честно в неймспейсы попадают? Решаются также, как конфликты имен типов. Вот, кстати, в расте тут с макросами "немного" коряво - на них неймспейсы не работают. Правда они импортируются явно, но переименовать, вроде, нельзя. |
![]() |
Сообщ.
#146
,
|
|
Цитата DarkEld3r @ Я тут кстати подумал, а кто не даёт-то? Выбирай костыль:Кстати, ещё один вопрос - в С++ ведь нельзя шаблонным параметрам-функциям нормально ограничить сигнатуру. ![]() ![]() template <typename T> struct check; template <> struct check<int(int)>{}; template <typename T> struct impl : check<T> { static void doIt(T *t) { /* ... */ } }; template <typename T> void f(T *t) { return impl<T>::doIt(t); } ![]() ![]() template <typename T> struct check; template <> struct check<int(int)>{}; template <typename T> void f(T *t) { check<T>(); /* ... */ } ![]() ![]() template <int (*t)(int)> void f() { /* ... */ } |
Сообщ.
#147
,
|
|
|
Qraizer, думаю, что имеются в виду любые объекты-функции.
|
Сообщ.
#148
,
|
|
|
Цитата Qraizer @ Так вот именно, что костыль. Выбирай костыль: ![]() Я ж не утверждал, что сделать нельзя и тем более того, что оно часто/сильно надо. Просто в расте синтаксически оно практически одинаково. Как аналог std::function для нешаблонных функций, так и дженерики. |
![]() |
Сообщ.
#149
,
|
|
Тогда ждём концептов, которые дадут нам явные трейты вместо утиных. А до тех пор -- костылить их руками.
|
Сообщ.
#150
,
|
|
|
Цитата DarkEld3r @ Цитата Qraizer @ Так вот именно, что костыль. Выбирай костыль: ![]() Я ж не утверждал, что сделать нельзя и тем более того, что оно часто/сильно надо. Просто в расте синтаксически оно практически одинаково. Как аналог std::function для нешаблонных функций, так и дженерики. А эти костыли точно делают то, что ты хотел? |