LINUX.ORG.RU

Задачка для ума. Из С++, но язык значения не имеет - главное типизация


1

2

Есть функция. Она должна в списке объектов найти объект по заданым свойствам.

Что делать, если функция не нашла объект?

Бросить исключение - не хочется. Понятие пустого объекта нет.

★★★★
Ответ на: комментарий от anonymous

я могу просто вернуть объекта A (точнее его копию)

А так если будет объект B, наследуюемый от A - то А должен быть создан

namezys ★★★★
() автор топика

Э... ну так тогда вариантов (простых) не так и много. Объект по ссылке, объект по значению и флаг типа bool по ссылке...

МОжно вернуть пару (объект,bool) , объект тогда все равно создавать, но должен же у него быть дефолтный конструктор какой то?

AIv ★★★★★
()
Ответ на: комментарий от AIv

Хотя я бы сделал через исключение, раз уж такие ограничения...

AIv ★★★★★
()

можно реализовать метод have - пусть он вернёт true если объект есть в контейнере, заодно положит сам объект в локальный кеш, из которого последующий вызов search его быстро-быстро получит :)

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

MKuznetsov ★★★★★
()
Ответ на: комментарий от namezys

Меня дяди учили, что класс должен иметь дефолтный конструктор. Иначе им вроде как низя буде в STL играться, и вообще... как то странно, если ф-я ВСЕГДА возвращает объект по значению, то даже если объект создать не возможно он должен быть как то создан. Прадокс... или кидать исключение.

Я не очень понял задачу наверное, память то кто под объект выделяет? Если она уже выделена (объект в списке лежит ведь?), то не грех и пойнтер на него вернуть, и итератор.

AIv ★★★★★
()
Ответ на: комментарий от AIv

> Иначе им вроде как низя буде в STL играться, и вообще...

Ну на фиг мне такие радости.

Я не очень понял задачу наверное, память то кто под объект выделяет

Пусть на стеке и выделяется.

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

тогда только способ №2 - функция должна вернуть итератор (или какую другую обёртку), который может быть пустым. Заодно так снимается вопрос который встанет дальше - если в упомянутом списке несколько объектов подходят под условия поиска - чё делать :)

MKuznetsov ★★★★★
()
Ответ на: комментарий от namezys

Не получается у меня с Вами согласиться. По моей кривой логике - это ошибка в области вызываемой функции и, если она не может быть автоматически обработана в ней, то всегда должна явно обрабатываться в вызвавшей функции любым изложенным способом(лучше общепринятым и наиболее удобным для C++ try-catch). Иначе - это допущения, ведущие к неопределённостям в будущем. Я так щитаю...

backbone ★★★★★
()
Ответ на: комментарий от namezys

Добавить в объект поле валиден/невалиден?

А кто его потом будет грохать. Не люблю я их

Можно использовать не указатель, а передачу объекта по ссылке. Но тогда нужен будет оператор копирования определить.

trex6 ★★★★★
()

>Задачка для ума

Точно для ума? По мне так больше для левой чакры

ttnl ★★★★★
()

Создай шаблонный тип Maybe. У него два метода: bool isNothing() и T& getJust(). Первый отвечает на вопрос нашли ли мы чего-нибудь, второй — отдаёт результат. Вариант плох тем, что не ясно что возвращать если для пустого ответа дёрнуть getJust. По хорошему исключение, чтобы головой думал.

KblCb ★★★★★
()

boost::optional

Вообще странно, что ни один из лоровских цпп-аналитиков не дал правильного ответа на этот вопрос.

V_L_A_D ★★
()
Ответ на: комментарий от MKuznetsov

> тогда только способ №2 - функция должна вернуть итератор (или какую другую обёртку), который может быть пустым.

Это да. Вообще можно вернуть список. Но кошерность вот в чем.

Пусть надо вернуть тип A

Обертка (итератор) будет либо class B { A* a; } либо class B { A a; }

Второе работать не будет. Первое не кошерно.

ЗЫ: надо идти спать, это уже загон

namezys ★★★★
() автор топика
Ответ на: комментарий от backbone

> По моей кривой логике - это ошибка в области вызываемой функции и, если она не может быть автоматически обработана в ней

Согласен.

Но для find или contains отсутствие элемента не является ошибкой.

А вот для get это ошибка

namezys ★★★★
() автор топика
Ответ на: комментарий от trex6

> Можно использовать не указатель, а передачу объекта по ссылке. Но тогда нужен будет оператор копирования определить.

По ссылке на что?

Если на созданный на стеке объект - его грохнут при раскрутке. Если на существующий в списке - то по фиг, есть или нет оператор копирования

namezys ★★★★
() автор топика
Ответ на: комментарий от V_L_A_D

Я немножко другое имел в виду. Но все это из разряда абстрактных умозаключений, которые на практике неприминимы

namezys ★★★★
() автор топика
Ответ на: комментарий от V_L_A_D

мне логика нужна была. а не реализация

namezys ★★★★
() автор топика

Если ваши свойства - линейный порядок, то логично использовать std::equal_range, но прочитав веточку, вы считаете это некошерным решением (обёрткой).

Вообщем мой совет, почитать Александресочку, чё он там недавненько про Ъ range и не Ъ итераторы писал ;)

nikitos ★★★
()
Ответ на: комментарий от nikitos

>Вообщем мой совет, почитать Александресочку

Да, Александреску — мастер по придумыванию костылей для обхода недоработок C++.

elverion
()
Ответ на: комментарий от nikitos

Да у него же весь «Modern C++ desing» так и построен:

1. Натыкаемся на подводный камень

2. Придумываем workaround, часто с использованием низкоуровневых средств оставшихся в наследство от C или использование средств языка не по назначению (один выбор типа через sizeof чего стоит).

3. goto 1

И я же не говорю что это плохо. Мне книга понравилась, и цепепе тоже нравится.

elverion
()
Ответ на: комментарий от namezys

Я имел ввиду - передавать объект по ссылке в функцию.
Что-то типа
bool foo(MyClass& object);

Насколько я помню, это как раз и называеться передача объекта по ссылке в противовес передачи объекта по значению.

trex6 ★★★★★
()
Ответ на: комментарий от namezys

> А так если будет объект B, наследуюемый от A - то А должен быть создан

Ну и создай себе один объект, в чем проблема?

anonymous
()
Ответ на: комментарий от trex6

> Насколько я помню, это как раз и называеться передача объекта по ссылке в противовес передачи объекта по значению.

Вы помните правильно, но конструктор копирования тут не нужен;-)

В общем, для решения задачи есть всего три варианта:

1) возврат объекта (по ссылке, значению, как угодно) или генерация исключения

2) возврат объекта + флаг валидности

3) возврат пойнтера (итератора) на объект.

Если память выделяется на стеке, то третий вариант отпадает.

Дальше уже детали дизайна и реализации, рюшечки-бантики, как паковать-прятать флаг валидности, как возвращать объект, но какой то вариант выбрать придется;-)

Например можно поиск проводить в конструкторе некоего класса, который будет у себя в потрошках хранить результаты поиска, в поле валидность и по запросу (вызов метода) возвращать найденный объект... тут мильен вариантов.

AIv ★★★★★
()
find :: (a -> Bool) -> [a] -> Maybe a

Принимает: (a -> Bool) — предикат для поиска, [a] — список элементов. Возвращает: Maybe a (Just a — если нашелся элемент, соответствующий предикату; Nothing — если не нашелся).

sanuda
()

Можно еще нечто асинхронное сделать, ну например на сигналах/слотах в qt или просто на эвентах.

Gorthauer ★★★★★
()

Тред не читал

Возвращать индекс в списке, -1 если не найдет. Брать объект по индексу другой функцией.

kir4
()
Ответ на: комментарий от trex6

> Насколько я помню, это как раз и называеться передача объекта по ссылке в противовес передачи объекта по значению.

Для этого объект должен быть сконструирован. И иметь симантику присвоения

namezys ★★★★
() автор топика
Ответ на: комментарий от anonymous

> Ну и создай себе один объект, в чем проблема?

А какой конструтор у него будет, если объект не найден?

namezys ★★★★
() автор топика

boost::optional или самописная поделка типа того (как у меня).

JackyTreehorn
()
Ответ на: Тред не читал от kir4

> Возвращать индекс в списке, -1 если не найдет. Брать объект по индексу другой функцией.

Ой. Ну нет

namezys ★★★★
() автор топика
Ответ на: комментарий от JackyTreehorn

> Какой заяц? Какой орел? Какая блоха? Какое free? Это же с++.

В этом и весь ужас, что человек написал фрее

namezys ★★★★
() автор топика
Option[MyObject] findObject(...) {
    ...
    return Some(x);
    ...
    return None;
}

findObject(...) match {
    case Some(x) => ... // найдено
    case None => ... // не найдено
}
Legioner ★★★★★
()
Ответ на: комментарий от namezys

>> Возвращать индекс в списке, -1 если не найдет. Брать объект по индексу другой функцией.

Ой. Ну нет


Почему это «ну нет»? Лучшее решение из тех, что я тут видел, помимо итератора, который по сути то же самое.

anonymous
()
Ответ на: комментарий от mi_estas

> и после этого ты отказываешься возвращать указатель?! (громкий истерический смех)

указатели ЗЛО

namezys ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.