2016-01-18 1 views
0

, который мой шаблон-функция:Поиск Выбор диапазона Generic для члена с конкретным полем

template<class DataStruct> 
    static bool isPlayerIn(DataStruct players, int id){ 
     for(DataStruct::iterator player = players.begin(); 
       player != players.end(); ++player){ 
      if((*player)->_id == id){ 
       return true; 
      } 
     } 
     return false; 
    } 

Я хочу, чтобы иметь возможность получить игроков как вектор и как карта, или любой другой STL. Я не могу использовать алгоритм find, потому что я ищу «игрока», у которого внутренний идентификатор поля такой же, как заданный параметр. Есть ли способ этой работы?

Он complaines о:

(*player)->_id 

Потому что он не знает, что игрок является PTR в PTR к классу игрока.

+1

Или, может быть, я могу использовать этот случай find_if? – KittyT2016

+1

Я бы использовал 'std :: find_if' – NathanOliver

+0

, который вы могли бы явно использовать как указатель класса игрока (возможно, не проверял) – Bort

ответ

1

Так как вы просили об этом, вы могли бы поставить лямбда в функции isSameID, если она будет использоваться в нескольких местах. Вероятно, это также облегчит чтение, когда вы получите код обслуживания.

template <class ContType> 
bool isSameID(ContType cont, int id) { 
    auto found = find_if(begin(cont), end(cont), [id] (auto item) { 
     return item->_id == id; 
    }); 
    return found != end(cont); 
} 

Эта функция предполагает, что контейнер передан, и вы используете C++ 14.

Update 1: Самый быстрый способ заставить его работать на обоих map и vector было бы просто выделить _id извлечения из функции, и пусть компилятор выбрать правильный путь, чтобы получить _id для данного контейнера тип. Я также удаляла auto за ваш запрос и переключился на прохождение контейнера по const&, чтобы избежать изготовления копий:

int GetID(const pair<int, Player*>& item) { 
     return item.second->_id; 
    } 
    int GetID(Player* item) { 
     return item->_id; 
    } 

    template <class ContType> 
     bool isSameID(const ContType& cont, int id) { 
      typename ContType::const_iterator found = find_if(begin(cont), end(cont), 
       [id] (typename ContType::value_type item) { 
       return GetID(item) == id; 
      }); 
      return found != end(cont); 
     } 
+0

Как я могу избежать использования auto (поскольку я знаю, что при компиляции в качестве авто и его не нужно использовать уникальный флаг, и я не хочу его использовать)? Как я понимаю, запись конкретного типа будет выполнять работу: Player * в моем случае – KittyT2016

+0

И в этом случае есть ли какое-либо решение для контейнера карты, потому что оно содержит пары? Это будет работать для vectro, deque и этого материала, но для карты, которая является настоящим беспорядком, не так ли? Вы видите более общее решение, которое будет работать для вектора и для карты как? – KittyT2016

+0

Какой тип вашей карты? – bsruth

0

у вас возникла проблема с вашей инкапсуляцией, так как функция dos не знает, что такое DataStruct, она не может напрямую отключить внутренний итератор. , если вы реализуете оператор де-ссылки для итератора, он будет работать.

в итератора добавить:

objStored *operator(){ 
    return **this; 
} 

затем в проигрывателе OBJ добавить метод, чтобы получить идентификатор:

int getId(){ 
return this->id; 
} 

и вместо (*player)->_id == id записи (*player)->getId()

этот путь любой класс которые имеют в итераторе, который удерживает (каким-либо образом) объект, который поддерживает (каким-либо образом) метод getId.

Если вы используете шаблоны для создания общей функции, вы не должны ее делать, поэтому она будет работать только для класса с итератором, который является указателем на указатель на игроков, имеющих член _id. старайтесь меньше думать о своих объектах.

1

Использование C++ 11, вы можете легко использовать find_if с lambda function:

[=](const typename DataStruct::value_type &v){return v._id == id;} 

где вообще вы бы использовать что-то вроде

auto has_id = [=](const typename DataStruct::value_type &v){return v._id == id;}; 

return std::find_if(
    std::begin(players), 
    std::end(players), 
    has_id) != std::end(players); 
+0

Да, это именно то, что я ищу, но я не понимаю typename DataStruct, и еще одна вещь, если я не хочу использовать auto, могу ли я просто написать bool вместо этого? – KittyT2016

+0

Вы не можете написать '' bool'', так как его тип - это лямбда-функция, которая совершенно иная. –

+0

Как я вижу, это решение плохо для типа контейнера карты, в котором содержатся пары, а вторая из них - это мой «v», как вы его написали. Любое решение, чтобы сделать его совместимым с контейнером карты? – KittyT2016