Перегрузка методов с лямбдами
От: Kingofastellarwar Украина  
Дата: 07.01.17 11:43
Оценка:
    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 г.
Отредактировано 07.01.2017 11:44 Barbar1an . Предыдущая версия .
Re: Перегрузка методов с лямбдами
От: night beast СССР  
Дата: 07.01.17 12:00
Оценка: +1
Здравствуйте, Kingofastellarwar, Вы писали:

K>
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-> поставь.
Re: Перегрузка методов с лямбдами
От: Went  
Дата: 07.01.17 16:58
Оценка: +2
Здравствуйте, Kingofastellarwar, Вы писали:
K>как ?
По-моему, не зря в STL есть std::find и std::find_if отдельно. А ведь тоже могли бы перегрузить. Не стоит этого делать, функции ведь по смыслу разные. Я вообще пользуюсь правилом "не перегружайте функции, если без этого можно обойтись". В любом случае, набор перегрузок, среди которой есть "любое T" — это плохая идея уже сама по себе. Чревато ошибками, когда программист будет ожидать неявного приведения аргумента и вызова соответствующей функции, а получать будет постоянно "универсальный" шаблон.
Re: Перегрузка методов с лямбдами
От: uzhas Ниоткуда  
Дата: 07.01.17 17:47
Оценка: +1
Здравствуйте, Kingofastellarwar, Вы писали:

K>как ?


прошу выкладывать код в онлайн компилятор. ссылки есть в прикрепленной ветке
ответ на вопрос: вот так http://ideone.com/0i6jPE
Re: Перегрузка методов с лямбдами
От: Кодт Россия  
Дата: 07.01.17 17:57
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

Можно (взять готовый в 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); }


Вот наколбасил эксперимент
http://ideone.com/SQNwIS
  Скрытый текст
#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 — в инфинитиве/императиве.
Перекуём баги на фичи!
Отредактировано 08.01.2017 17:48 Кодт . Предыдущая версия .
Re[2]: Перегрузка методов с лямбдами
От: Burbulis1978  
Дата: 07.04.17 16:51
Оценка: +2
Здравствуйте, uzhas, Вы писали:

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


K>>как ?


U>прошу выкладывать код в онлайн компилятор. ссылки есть в прикрепленной ветке

U>ответ на вопрос: вот так http://ideone.com/0i6jPE

А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!
Re[3]: Перегрузка методов с лямбдами
От: night beast СССР  
Дата: 07.04.17 16:55
Оценка:
Здравствуйте, Burbulis1978, Вы писали:

U>>прошу выкладывать код в онлайн компилятор. ссылки есть в прикрепленной ветке

U>>ответ на вопрос: вот так http://ideone.com/0i6jPE

B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!


какие именно проблемы видишь в выложенном коде?
Re[3]: Перегрузка методов с лямбдами
От: swingus  
Дата: 08.04.17 14:30
Оценка: +1
Вот по поводу виртуальных деструкторов — это какой-то ложный аргумент, кочующий по форумам и собеседованиям. Классу нужен виртуальный деструктор только если его требуется удалять через указатель базы, а значительная часть приёмов C++ программирования вообще не требует виртуальных таблиц. И уж требовать виртуальных деструкторов от контейнеров — вообще экзотика.

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

B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!
Re[3]: Перегрузка методов с лямбдами
От: Ops Россия  
Дата: 09.04.17 08:21
Оценка: +4
Здравствуйте, Burbulis1978, Вы писали:

B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!


Ну вот пока ты так считаешь, так и делай.
Тут ведь вопрос в том, что у такого унаследованного класса всего лишь нет динамического полиморфного удаления, что далеко не всегда вообще нужно.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[3]: Перегрузка методов с лямбдами
От: MasterZiv СССР  
Дата: 11.04.17 09:47
Оценка:
Здравствуйте, Burbulis1978, Вы писали:

B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!


Какую только хрень в интернете не понапишут...
Re[3]: Перегрузка методов с лямбдами
От: uzhas Ниоткуда  
Дата: 11.04.17 12:12
Оценка:
Здравствуйте, Burbulis1978, Вы писали:

B>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!


оказывается, это распространенное заблуждение
Re[4]: Перегрузка методов с лямбдами
От: Кодт Россия  
Дата: 17.04.17 10:22
Оценка: :)
Здравствуйте, uzhas, Вы писали:

B>>А я вот читал что нельза наследоваться от стандартных контейнеров, у них ет виртуальных деструкторов и в некоторых нежелательных случаях может быть ай! яй! яй!


Узаю старый добрый фидоет!

U>оказывается, это распространенное заблуждение


Мне мама говорила всегда: "не ешь тесто — кишки слипнутся, придётся операцию делать!"
Я верил до... 20 лет. Потом, когда подумал, сказал:
— Мама, так ты меня ВСЮ ЖИЗНЬ обманывала?
— Конечно, зато ты у меня никогда тесто не ел...


Наследоваться можно, но потом придётся тщательно следить за чистотой рук и/или бороться с возможностью ошибок.
Проще сразу отучить людей программировать мясом наружу, и оставлять у клиентского типа только минимально необходимые детали интерфейса.
Перекуём баги на фичи!
Re[4]: Перегрузка методов с лямбдами
От: niXman Ниоткуда https://github.com/niXman
Дата: 18.04.17 07:57
Оценка:
Здравствуйте, swingus, Вы писали:

S>Вот по поводу виртуальных деструкторов — это какой-то ложный аргумент, кочующий по форумам и собеседованиям. Классу нужен виртуальный деструктор только если его требуется удалять через указатель базы, а значительная часть приёмов C++ программирования вообще не требует виртуальных таблиц. И уж требовать виртуальных деструкторов от контейнеров — вообще экзотика.


неизвестно, как и кем будет использоваться написанный таким образом код далее. никогда не наследую контейнеры, почти всегда добавляю виртуальный деструктор.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 18.04.2017 8:00 niXman . Предыдущая версия .
Re[5]: Перегрузка методов с лямбдами
От: niXman Ниоткуда https://github.com/niXman
Дата: 18.04.17 07:59
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Узаю старый добрый фидоет!

"фидоет" — это что?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[6]: Перегрузка методов с лямбдами
От: Кодт Россия  
Дата: 18.04.17 10:08
Оценка: +1
Здравствуйте, niXman, Вы писали:

К>>Узаю старый добрый фидоет!

X>"фидоет" — это что?

Это в древности была фигня с кодировками в фидошном клиенте, русская буква "Н" зарезерирована под управляющий символ.

МЕЯ ВИДО? -- ЕТ!
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.