std::set_difference z własną klasą

Odpowiedz Nowy wątek
2013-06-11 19:09

Rejestracja: 11 lat temu

Ostatnio: 5 lat temu

0

Witajcie,

co muszę zrobić, aby std::set_difference działał mi z własną klasą? Co muszę do takiej klasy dorzucić?
Dorzuciłem już const_iterator'y i iterator'y (begin() i end()). Czego jeszcze brakuje? Jakichś operatorów?

MojaKlasa roznica;
MojaKlasa rezultat;
MojaKlasa drugiRezultat;

std::set_difference( rezultat.begin(), rezultat.end(),
 drugiRezultat.begin(), drugiRezultat.end(),
 std::inserter( roznica, roznica.begin() ) );

Kiedy działam na std::vector to kod powyżej działa. Jeżeli działam na MojaKlasa to wywala:

Error 1 error C2893: Failed to specialize function template 'std::insert_iterator<_Container> std::inserter(_Container &,_Container::iterator)'
Error 2 error C2780: '_OutTy *std::set_difference(_InIt1,_InIt1,_InIt2,_InIt2,_OutTy (&)[_OutSize],_Pr)' : expects 6 arguments - 5 provided
Error 3 error C2780: '_OutIt std::set_difference(_InIt1,_InIt1,_InIt2,_InIt2,_OutIt,_Pr)' : expects 6 arguments - 5 provided

Proszę o pomoc.


~Jeśli jeszcze nie zwariowałeś, tzn. że jesteś niedoinformowany...
edytowany 1x, ostatnio: SkyLiNe, 2013-06-11 19:14
zaimplementować iterator - _13th_Dragon 2013-06-11 19:33

Pozostało 580 znaków

2013-06-11 20:01

Rejestracja: 16 lat temu

Ostatnio: 4 godziny temu

0

Failed to specialize function template 'std::insert_iterator<_Container> std::inserter(_Container &,_Container::iterator)'

Błąd pierwszy mówi o problemie z std::inserter, a nie std::set_difference. Na tym się skup.

Masz też podaną od razu deklarację tej funkcji. Widać że drugi parametr jest typu _Container::iterator. Masz taki typ wewnątrz swojej klasy?

Pozostało 580 znaków

2013-06-11 20:34

Rejestracja: 11 lat temu

Ostatnio: 5 lat temu

0
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>

class MojaKlasa
{
    std::vector< int > moje;

public:
    std::vector< int >::iterator begin()
    {
        moje.begin();
    }

    std::vector< int >::iterator end()
    {
        moje.end();
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    MojaKlasa roznica;
    MojaKlasa rezultat;
    MojaKlasa drugiRezultat;

    std::set_difference( rezultat.begin(), rezultat.end(),
    drugiRezultat.begin(), drugiRezultat.end(),
    std::inserter( roznica, roznica.begin() ) );
    return 0;
}

Tak to wygląda.. Czym jest owy _Container?


~Jeśli jeszcze nie zwariowałeś, tzn. że jesteś niedoinformowany...

Pozostało 580 znaków

2013-06-11 20:41

Rejestracja: 16 lat temu

Ostatnio: 4 godziny temu

0

Czym jest owy _Container?
Twoją klasą.

Na pewno musisz dodać w klasie publicznie typedef o nazwie iterator. Skoro używasz wewnętrznie vectora, to możesz użyć jego iteratora.

class MojaKlasa
{
  public:
        typedef std::vector< int >::iterator iterator;

na tym się zapewne nie skończy.

EDIT: tu masz opis std::inserter() wraz z wymaganiami http://www.cplusplus.com/reference/iterator/inserter/
a tutaj co dokładnie powinien zawierać "container": http://en.cppreference.com/w/cpp/concept/Container
(nie wszystko musi być wymagane przez inserter())

edytowany 1x, ostatnio: Azarien, 2013-06-11 20:53

Pozostało 580 znaków

2013-06-11 22:36

Rejestracja: 11 lat temu

Ostatnio: 5 lat temu

0
class MojaKlasa
{
    std::vector< int > moje;

public:
    typedef std::vector< int >::iterator iterator;

    iterator begin()
    {
        moje.begin();
    }

    iterator end()
    {
        moje.end();
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    MojaKlasa roznica;
    MojaKlasa rezultat;
    MojaKlasa drugiRezultat;

    std::set_difference( rezultat.begin(), rezultat.end(),
    drugiRezultat.begin(), drugiRezultat.end(),
    std::inserter( roznica, roznica.begin() ) );
    return 0;
}

Jak to jest, że dodałem tego typedef'a i rzuca już całkowicie innymi błędami? Przecież poprzednio było tak samo... typedef jest jak using... zwykły alias. Mogę prosić o wytłumaczenie jak to kompilator zinterpretował? Nigdy jeszcze nie opakowywałem kontenera, dlatego może trywialne pytania, ale dla mnie dość ciężkie... Teraz mam błędy:

Error 1 error C2039: 'const_reference' : is not a member of 'MojaKlasa' c:\program files (x86)\microsoft visual studio 10.0\vc\include\iterator
Error 2 error C2146: syntax error : missing ';' before identifier 'const_reference' c:\program files (x86)\microsoft visual studio 10.0\vc\include\iterator
Error 3 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\program files (x86)\microsoft visual studio 10.0\vc\include\iterator
Error 4 error C2602: 'std::insert_iterator<_Container>::const_reference' is not a member of a base class of 'std::insert_iterator<_Container>' c:\program files (x86)\microsoft visual studio 10.0\vc\include\iterator
Error 5 error C2868: 'std::insert_iterator<_Container>::const_reference' : illegal syntax for using-declaration; expected qualified-name c:\program files (x86)\microsoft visual studio 10.0\vc\include\iterator
Error 6 error C2039: 'value_type' : is not a member of 'MojaKlasa' c:\program files (x86)\microsoft visual studio 10.0\vc\include\iterator
Error 7 error C2182: '_Val' : illegal use of type 'void' c:\program files (x86)\microsoft visual studio 10.0\vc\include\iterator
Error 8 error C2182: '_Val' : illegal use of type 'void' c:\program files (x86)\microsoft visual studio 10.0\vc\include\iterator

EDIT
OK już coraz bliżej:

#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>

class MojaKlasa
{
    std::vector< int > moje;

public:
    typedef std::vector< int >::iterator iterator;
    typedef std::vector< int >::const_reference const_reference;
    typedef std::vector< int >::value_type value_type;

    iterator begin()
    {
        moje.begin();
    }

    iterator end()
    {
        moje.end();
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    MojaKlasa roznica;
    MojaKlasa rezultat;
    MojaKlasa drugiRezultat;

    std::set_difference( rezultat.begin(), rezultat.end(),
    drugiRezultat.begin(), drugiRezultat.end(),
    std::inserter( roznica, roznica.begin() ) );
    return 0;
}

Error 1 error C2039: 'insert' : is not a member of 'MojaKlasa' c:\program files (x86)\microsoft visual studio 10.0\vc\include\iterator

Teraz tylko jak zrobić tego insert'a... Jeszcze raz proszę o wytłumaczenie mi skąd kompilator wie, że te wszystkie typedef'y tyczą się tych rzeczy... W C# implementuje się IEnumerable i jest z górki, a tutaj nic nie jest implementowane, a kompilator wie, że ta klasa ma się tak zachowywać...


~Jeśli jeszcze nie zwariowałeś, tzn. że jesteś niedoinformowany...
edytowany 2x, ostatnio: SkyLiNe, 2013-06-12 00:47

Pozostało 580 znaków

2013-06-12 07:56

Rejestracja: 11 lat temu

Ostatnio: 3 lata temu

0

W skrócie: funkcje STL są szablonowe i zakładają, że typ, na którym mają operować, udostępnia pewien interfejs. To jest w zasadzie analogiczne do implementacji IEnumerable.

Spójrz na deklarację inserter:

template<typename Container>
  insert_iterator<Container> inserter(Container& x, typename Container::iterator it);

Metoda zakłada, że typ na jakim ma operować, udostępnia podtyp iterator – po to właśnie potrzebny jest typedef.

insert() musisz również zaimplementować (a w zasadzie owrappować ten z twojego kontenera). Raczej nie musisz wrappować wszystkich, powinno wystarczyć iterator insert (const_iterator position, const value_type& val).

A tutaj, jak widzisz, zakładany jest w interfejsie const_iterator; jego też powinieneś zadeklarować przez typedef.


edytowany 2x, ostatnio: rincewind, 2013-06-12 10:02

Pozostało 580 znaków

2013-06-12 19:46

Rejestracja: 16 lat temu

Ostatnio: 4 godziny temu

C# implementuje się IEnumerable i jest z górki, a tutaj nic nie jest implementowane

w C++ jest podobnie: klasa ma zawierać to i to i to i to, ale nie ma pojęcia „interfejsu”, przez co jest trudniej się dowiedzieć co trzeba zaimplementować...

a kompilator wie, że ta klasa ma się tak zachowywać...
Kompilator „nic nie wie”. Skoro inserter() używa gdzieś wewnętrznie metody insert() na podanym obiekcie, to siłą rzeczy klasa musi taką metodę posiadać. Jest to podobny mechanizm do typu dynamic w C#: samo użycie danej metody powoduje wymóg jej istnienia.

Pozostało 580 znaków

2013-06-12 22:40

Rejestracja: 11 lat temu

Ostatnio: 5 lat temu

0
#include "stdafx.h"
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>

class MojaKlasa : public std::vector< int >{};

int _tmain(int argc, _TCHAR* argv[])
{
    MojaKlasa roznica;
    MojaKlasa rezultat;
    MojaKlasa drugiRezultat;

    std::set_difference( rezultat.begin(), rezultat.end(),
    drugiRezultat.begin(), drugiRezultat.end(),
    std::inserter( roznica, roznica.begin() ) );
    return 0;
}

Tak to się skończy :).
Dzięki za rozjaśnienie tematu.


~Jeśli jeszcze nie zwariowałeś, tzn. że jesteś niedoinformowany...
a myślałem że ten vector to tylko tak na próbę, że chcesz się jednak nauczyć jak zaimplementować ten inserter... :-/ - Azarien 2013-06-13 00:28

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0