Заблокирован
1

Std::set, как добавить собственную проверку уникальности для класса?

28.08.2014, 11:05. Показов 3944. Ответов 28
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Сразу к делу
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Doc
{
public:
    Doc(){}
    ~Doc(){}
 
    std::wstring name;
    int id;
 
    bool operator==(const Doc& doc) const
    {
        if ((name == doc.name) && (id == doc.id))
            return true;
        else
            return false;
    }   
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    Doc d1, d2;
    d1.name = L"FIRST"; d1.id = 3;
    d2.name = L"FIRST"; d2.id = 3;
 
    std::set<Doc> ass;
    ass.insert(d1);
    ass.insert(d2);
 
    return 0;
}
хочу добавить в std::set экземпляры класса, естественно set не знает, как их проверять на идентичность, вот что надо реализовать в классе, чтоб всё это работало ? Если можно, прямо на этом примере чирканите пару строк
P.S.: так - то ясен пень не собирается

Добавлено через 4 минуты
думал вставить лямбду, тоже не работает
C++
1
2
3
    std::set<Doc, [](const Doc& a, const Doc& b){ return ((a.name == b.name) && (a.id == b.id)); }> ass;
    ass.insert(d1);
    ass.insert(d2);
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.08.2014, 11:05
Ответы с готовыми решениями:

Как правильно добавить в Set объекты своего класса?
Всем привет. Собственно меня интересует вопрос как правильно добавить в Set объекты своего класса....

Как сделать проверку уникальности наименования у справочника 1С:Предприятие 8.3?
Как сделать проверку уникальности наименования у справочника 1С:Предприятие 8.3?

STL std::set, std::pair, std::make_pair
Я не знаю как описать тему в двух словах, поэтому не обращайте внимание на название темы....

Конструктор для std::set
struct TrainFilterCompany { TrainFilterCompany ( const set&lt;string&gt; &amp; companies ) :...

28
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
28.08.2014, 11:11 2
Цитата Сообщение от -NEURON- Посмотреть сообщение
думал вставить лямбду, тоже не работает
Потому что нужен тип, а не объект.

Добавлено через 3 минуты
По умолчанию компаратор - std::less<T>, следовательно, должен быть оператор <.
1
Заблокирован
28.08.2014, 11:13  [ТС] 3
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Doc
{
public:
    Doc(){}
    ~Doc(){}
 
    std::wstring name;
    int id; 
};
 
struct DocComp
{
    bool operator() (const Doc& a, const Doc& b) const
    {       
        return a.name < b.name;
    }
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    Doc d1, d2;
    d1.name = L"FIRST"; d1.id = 3;
    d2.name = L"FIRST"; d2.id = 3;
    
    std::set<Doc, DocComp > ass;
    ass.insert(d1);
    ass.insert(d2);
 
    return 0;
}
вот так заработало, но у меня вопрос, а как он оператором < проверяет уникальность объекта - то ?

И ещё вопрос, как без функтора написать такую лямбду прямо в объявление set, чтоб код не плодить ?
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
28.08.2014, 11:15 4
Цитата Сообщение от -NEURON- Посмотреть сообщение
вот так заработало, но у меня вопрос, а как он оператором < проверяет уникальность объекта - то ?
!(a < b) && !(b < a) => a == b
1
Заблокирован
28.08.2014, 11:17  [ТС] 5
Цитата Сообщение от 0x10 Посмотреть сообщение
!(a < b) && !(b < a) => a == b
ясно, спасибо, а как всё таки предикат правильно записать прямо в объявление set? что - то не получается ...
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
28.08.2014, 11:20 6
Цитата Сообщение от -NEURON- Посмотреть сообщение
а как всё таки предикат правильно записать прямо в объявление set?
C++
1
2
auto comp = [](){...};
std::set<T, decltype(comp)> my_set(comp);
0
Заблокирован
28.08.2014, 11:21  [ТС] 7
Ну даже если не предикатом, можно ли как - то засунуть это проверку в сам класс, чтоб объявлять set по обычному std::set<Doc> и компилятор бы уже знал, как это дело проверять ...
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
28.08.2014, 11:21 8
Цитата Сообщение от -NEURON- Посмотреть сообщение
Ну даже если не предикатом, можно ли как - то засунуть это проверку в сам класс
Как уже говорил выше, оператор<, но мне это не кажется семантичным.
1
Заблокирован
28.08.2014, 11:28  [ТС] 9
Цитата Сообщение от 0x10 Посмотреть сообщение
но мне это не кажется семантичным.
Почему же? Засунул её в класс и забыл, а так придётся при каждом объявление в разных файлах писать этот функтор ...

Кстати, я пытался засунуть в класс - ничего не вышло - можете продемонстрировать set на примере функтора в классе?
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
28.08.2014, 11:40 10
Лучший ответ Сообщение было отмечено -NEURON- как решение

Решение

Цитата Сообщение от -NEURON- Посмотреть сообщение
Почему же?
1. С точки зрения интерфейса в классе появляется единственно возможный способ сортировки его объектов. По факту критериев сортировки может быть N, и я не вижу повода добавлять ограничений.
2. Утверждение "документ А меньше документа Б" не может однозначно определить отношение порядка между этими объектами, всегда требуется уточнение: по какому признаку?
Цитата Сообщение от -NEURON- Посмотреть сообщение
Кстати, я пытался засунуть в класс - ничего не вышло
Как пытались и почему не вышло?
1
Заблокирован
28.08.2014, 11:47  [ТС] 11
Цитата Сообщение от 0x10 Посмотреть сообщение
Как пытались и почему не вышло?
А... сам валенок, всё работает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Doc
{
public:
    Doc(){}
    ~Doc(){}
 
    std::wstring name;
    int id;
 
    bool operator< (const Doc& a) const
    {
        return name < a.name;
    }   
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    Doc d1, d2;
    d1.name = L"FIRST"; d1.id = 3;
    d2.name = L"FIRST2"; d2.id = 3;
    
    std::set < Doc > ass;
    ass.insert(d1);
    ass.insert(d2);
 
    return 0;
}
Просто по твоему совету не буду кидать в класс проверку . Всё, ладно. Спасибо!
0
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
28.08.2014, 11:52 12
Как вариант:

C++
1
2
static const auto pred = []( int, int ) { /* */ };
std::set<int, decltype( pred )> s( pred );
1
Заблокирован
28.08.2014, 12:02  [ТС] 13
Цитата Сообщение от Voivoid Посмотреть сообщение
decltype
а эта кроссовая штука или чисто под VS2013 ?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.08.2014, 12:05 14
-NEURON-, Это из стандарта С++11.
1
Заблокирован
28.08.2014, 12:08  [ТС] 15
Цитата Сообщение от ForEveR Посмотреть сообщение
-NEURON-, Это из стандарта С++11.
О..спасибо. А что эта штука фактический делает? В двух словах без отсылания к докам
0
Эксперт по математике/физикеЭксперт С++
2044 / 1363 / 393
Регистрация: 16.05.2013
Сообщений: 3,500
Записей в блоге: 6
28.08.2014, 12:18 16
Определяет тип возвращаемого значения
1
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.08.2014, 12:20 17
Лучший ответ Сообщение было отмечено -NEURON- как решение

Решение

-NEURON-, Определяет тип выражения на этапе компиляции.

Где например может быть полезна:

C++
1
2
3
4
5
template<typename T, typename U>
auto plus(T&& first, U&& second) -> decltype(first + second)
{
    return first + second;
}
Без decltype пришлось бы туго.

В С++14 можно будет писать вообще такой код:
C++
1
2
3
4
5
template<typename T, typename U>
auto plus(T&& first, U&& second)
{
    return first + second;
}
Нет явного использования decltype, но под капотом скорее всего будет работать именно он.
1
Заблокирован
28.08.2014, 12:27  [ТС] 18
Цитата Сообщение от ForEveR Посмотреть сообщение
auto plus(T&& first, U&& second) -> decltype(first + second)
ваще не понял эту строчку, но всё равно спасибо
0
Эксперт по математике/физикеЭксперт С++
2044 / 1363 / 393
Регистрация: 16.05.2013
Сообщений: 3,500
Записей в блоге: 6
28.08.2014, 12:29 19
Цитата Сообщение от -NEURON- Посмотреть сообщение
ваще не понял эту строчку, но всё равно спасибо
Тип возвращаемого значения выводится автоматическии как результат операции + для аргументов.
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.08.2014, 12:34 20
-NEURON-, Объясняю.
Возвращаемый тип функции plus определяется по сумме ее аргументов, при этом на самом деле оператор + вызван не будет да и decltype не будет использовать сами переменные, а просто найдет подходящую сигнатуру (скажем так,
C++
1
result_type operator + (T, U)
), посмотрит на возвращаемый тип и скажет какой он, все это естественно произойдет на этапе компиляции.
1
28.08.2014, 12:34
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.08.2014, 12:34
Помогаю со студенческими работами здесь

итераторами для std::set
Здравствуйте! Разбирая std::set и его итераторы столкнунлась с ужасающей проблемой: когда передаю...

Перегруженный оператор () для std::set
Зачем в СТЛ в контейренах типу SET и других перегружать оператор () вот код struct...

Сделать проверку уникальности ввода данных
Как сделать так, чтобы в структуре была проверка уникальности ввода данных? То есть чтобы когда я...

Шаблон как тип контейнера std::set
template&lt;class T&gt; int func(T&amp;, int); typedef std::ostream_iterator&lt;int&gt; out_in; int main() { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru