Здравствуйте, Burbulis1978, Вы писали:
B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!
Ну вот пока ты так считаешь, так и делай.
Тут ведь вопрос в том, что у такого унаследованного класса всего лишь нет динамического полиморфного удаления, что далеко не всегда вообще нужно.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Kingofastellarwar, Вы писали: K>как ?
По-моему, не зря в STL есть std::find и std::find_if отдельно. А ведь тоже могли бы перегрузить. Не стоит этого делать, функции ведь по смыслу разные. Я вообще пользуюсь правилом "не перегружайте функции, если без этого можно обойтись". В любом случае, набор перегрузок, среди которой есть "любое T" — это плохая идея уже сама по себе. Чревато ошибками, когда программист будет ожидать неявного приведения аргумента и вызова соответствующей функции, а получать будет постоянно "универсальный" шаблон.
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, Kingofastellarwar, Вы писали:
K>>как ?
U>прошу выкладывать код в онлайн компилятор. ссылки есть в прикрепленной ветке U>ответ на вопрос: вот так http://ideone.com/0i6jPE
А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!
K>CList<int> a;
K>a.Contain([](auto i){ return i == 5; }); //ok
K>a.Contain(5); //term does not evaluate to a function taking 1 arguments
K> // bool CList<int>::Contain<int>(Pred)' being compiled ??????
K>
K>как ?
не воспроизводится.
код на ideone.com закинь.
перед begin и end this-> поставь.
Вот по поводу виртуальных деструкторов — это какой-то ложный аргумент, кочующий по форумам и собеседованиям. Классу нужен виртуальный деструктор только если его требуется удалять через указатель базы, а значительная часть приёмов C++ программирования вообще не требует виртуальных таблиц. И уж требовать виртуальных деструкторов от контейнеров — вообще экзотика.
Здравствуйте, Burbulis1978, Вы писали:
B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!
Здравствуйте, uzhas, Вы писали:
B>>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!
Узаю старый добрый фидоет!
U>оказывается, это распространенное заблуждение
Мне мама говорила всегда: "не ешь тесто — кишки слипнутся, придётся операцию делать!"
Я верил до... 20 лет. Потом, когда подумал, сказал:
— Мама, так ты меня ВСЮ ЖИЗНЬ обманывала?
— Конечно, зато ты у меня никогда тесто не ел...
Наследоваться можно, но потом придётся тщательно следить за чистотой рук и/или бороться с возможностью ошибок.
Проще сразу отучить людей программировать мясом наружу, и оставлять у клиентского типа только минимально необходимые детали интерфейса.
template<class T> class CList : public std::list<T>
{
public:
template<class Pred> bool Contain(Pred p)
{
return std::find_if(begin(), end(), p) != end();
}
bool Contain(const T & v)
{
return std::find(begin(), end(), v) != end();
}
}
CList<int> a;
a.Contain([](auto i){ return i == 5; }); //ok
a.Contain(5); //term does not evaluate to a function taking 1 arguments
// bool CList<int>::Contain<int>(Pred)' being compiled ??????
как ?
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Можно (взять готовый в C++17 или навелосипедить свой) is_callable и использовать его в SFINAE
template<class P> auto contains(P&& p) ->
// если существует и приводится к bool выражение p(t), где t - элемент коллекции
std::enable_if< std::is_convertible< decltype(p(std::declval<T>())), bool >::value, bool >::type
{ return std::find_if(std::begin(*this), std::end(*this), std::forward<T>(p)) != std::end(*this); }
template<class V> auto contains(V&& v) ->
// если существует и приводится к bool выражение t == v
std::enable_if< std::is_convertible< decltype(std::declval<T>() == v), bool >::value, bool >::type
{ return std::find(std::begin(*this), std::end(*this), std::forward<V>(v)) != std::end(*this); }
#include <iostream>
#include <type_traits>
#include <vector>
#include <algorithm>
using namespace std; // это инициатива от ideone.com, пусть будет.template<class T> struct container {
vector<T> ts;
template<class F> auto contains(F&& f) const ->
typename enable_if< is_convertible< decltype(f(declval<T>())), bool >::value, bool >::type
{
cout << "predicate\n";
return find_if(begin(ts), end(ts), f) != end(ts);
}
template<class V> auto contains(V&& v) const ->
typename enable_if< is_convertible< decltype(declval<T>() == v), bool >::value, bool >::type
{
cout << "match\n";
return find(begin(ts), end(ts), v) != end(ts);
}
};
// чтобы жизнь мёдом не казалась: а вдруг предикат вернёт не bool, а что попало (здесь - указатель на член)struct XZ { void xz() {} };
typedef void(XZ::*unspecified_bool)();
unspecified_bool unspec(bool v) { return v ? &XZ::xz : (unspecified_bool)0; }
// заодно проверим, можно ли искать по ключу, условно-совместимому с типом элементовstruct ONE {};
unspecified_bool operator == (int x, ONE y) {
cout << "compare " << x << " to ONE...\n";
return unspec(x == 1);
}
int main() {
container<int> d { {0, 3, 1, 2} };
cout << d.contains([](double x) {
cout << "examine " << x << "...\n";
return unspec(x==1); })
<< endl;
cout << d.contains(ONE()) << endl;
}
Но, как уже сказали выше, лучше не создавать, а потом героически разруливать неоднозначность семантики, — а с самого начала завести contains и contains_if.
И кстати, с т.з. английского языка, the_container.contains(value), а не the_container.contain(value).
Предикат — в 3 лице ед.числе.
А внешняя функция-алгоритм — find, find_if — в инфинитиве/императиве.
Здравствуйте, Burbulis1978, Вы писали:
U>>прошу выкладывать код в онлайн компилятор. ссылки есть в прикрепленной ветке U>>ответ на вопрос: вот так http://ideone.com/0i6jPE
B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!
Здравствуйте, Burbulis1978, Вы писали:
B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!
Здравствуйте, Burbulis1978, Вы писали:
B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!
Здравствуйте, swingus, Вы писали:
S>Вот по поводу виртуальных деструкторов — это какой-то ложный аргумент, кочующий по форумам и собеседованиям. Классу нужен виртуальный деструктор только если его требуется удалять через указатель базы, а значительная часть приёмов C++ программирования вообще не требует виртуальных таблиц. И уж требовать виртуальных деструкторов от контейнеров — вообще экзотика.
неизвестно, как и кем будет использоваться написанный таким образом код далее. никогда не наследую контейнеры, почти всегда добавляю виртуальный деструктор.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)