[RISOLTO][C++]Problemi con back_inserter

di il
9 risposte

[RISOLTO][C++]Problemi con back_inserter

Salve a tutti.
Il mio problema riguarda l'utilizzo del back_inserter su una classe da me creata.

Guardando il quadro generale, l'obbiettivo era quello di creare (per scopi didattici) una classe str, semplificazione della classe string, tale classe si poggia sulla classe vec che senza troppa fantasia è a sua volta una semplificazione della classe standard vector in modo da semplificare la gestione della memoria. I back_inserter incriminati fanno parte della classe str e l'errore avviene in fase di compilazione.
Piccola nota, la classe vec di per sé è esente da problemi dato che è già stata utilizzata in alcune prove, ma a quanto pare litiga con il back_inserter.

Ecco la classe str (quel poco che c'è) e più precisamente il file str.h da cui nasce il mio problema:

#ifndef STR_H_
#define STR_H_

#include "vec.h"
#include "vec.cpp"
#include <algorithm>
#include <iterator>
#include <cstring>

class str{
  public:
	typedef vec<char>::size_type size_type;
	/* definition of copy-constructor, destructor or assignment-operator
	 * are not necessary this class uses those of vec class*/

	str(){} //call the default constructor that implicit use vec()
	str(size_type n,char c) : data(n,c){}
	str(const char* charset){
	  std::copy(charset,charset+std::strlen(charset),std::back_inserter(data));
	}
	template<class it> str(it begin,it end){
	  std::copy(begin,end,std::back_inserter(data));
	}

  private:
	vec<char> data;
};

#endif /* STR_H_ */
la righe incriminate sono le due chiamate alla funzione standard copy dove al loro interno spunta il back_inserter, dubito che il problema stia essenzialmente in questa classe quindi andiamo a vedere la classe vec.

Ecco qui l'header:


#ifndef VEC_H_
#define VEC_H_

#include <memory>
#include <cstddef>

template<class T> class vec{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		typedef size_t size_type;

		vec(){
			create();
		}
		explicit vec(size_type n,const T& el = T()){
			create(n,el);
		}
		vec(const vec<T>& v){
			create(v.begin(),v.end());
		}
		~vec(){
			uncreate();
		}

		void push_back(const T& el){
			if(last == limit)
				grow();
			appendElement(el);
		}
		iterator erase(iterator position){
			return eraseElement(position);
		}
		void clear(){
			clearItems();
		}

		T& operator[](size_type i){
			return data[i];
		}
		const T& operator[](size_type i)const{
			return data[i];
		}
		vec<T>& operator= (const vec<T>&);

		iterator begin(){
			return data;
		}
		const_iterator begin() const{
			return data;
		}
		iterator end(){
			return last;
		}
		const_iterator end() const{
			return last;
		}

		size_type size() const{
			return last - data;
		}
		size_type allocatedSpace()const{
			return limit - data;
		}
	private:
		iterator data; //point to the begin of data structure
		iterator last; //point to the last element stored (one past)
		iterator limit; //point to the the end of allocated space (one past)
		std::allocator<T> alloc; //object used to manage memory

		void create();
		void create(size_type, const T&);
		void create(const_iterator,const_iterator);
		void uncreate();
		void clearItems();
		void grow();
		void appendElement(const T&);
		iterator eraseElement(iterator);
		iterator eraseRange(iterator,iterator);
};



#endif /* VEC_H_ */
E qui il file cpp:

#include "vec.h"

template<class T> void vec<T>::create(){
	data = last = limit = 0;
}
template<class T> void vec<T>::create(size_type n, const T& el){
	data = alloc.allocate(n);
	last = limit = data+n;
	std::uninitialized_fill(data,last,el);
}
template<class T> void vec<T>::create(const_iterator begin, const_iterator end){
	data = alloc.allocate(end-begin);
	last = limit = std::uninitialized_copy(begin,end,data);
}
template<class T> void vec<T>::uncreate(){
	if(data){
		while(last != data)
			alloc.destroy(last--);
		alloc.deallocate(data, limit-data);
		data = limit = last = 0;
	}
}
template<class T> void vec<T>::clearItems(){
	while(last != data)
		alloc.destroy(last--);
}
template<class T> void vec<T>::grow(){
	size_type space = data?(limit-data)*2:1;
	iterator new_data = alloc.allocate(space);
	iterator new_last = std::uninitialized_copy(data,last,new_data);
	uncreate();
	data = new_data;
	last = new_last;
	limit = new_data + space;
}
template<class T> void vec<T>::appendElement(const T& el){
	alloc.construct(last++,el);
}
template<class T> vec<T>& vec<T>::operator=(const vec<T>& v){
	if(&v != this){
		uncreate();
		create(v.begin(),v.end());
	}
	return *this;
}
template<class T> T* vec<T>::eraseElement(iterator position){
	iterator pos = position+1;
	iterator next = pos;
	while(next != last){
		alloc.destroy(position);
		alloc.construct(position++,*next++);
	}
	alloc.destroy(position);
	last--;
	return pos;
}
Ecco il piccolo, innocente, main.

#include <iostream>
#include "str.h"

int main(){
	str s = str();
	return 0;
}
Postato il codice è giunta l'ora di postare l'errore che, data la mia inesperienza in c++, fatico a comprendere, ecco qui:

 **** Build of configuration Debug for project Project ****

**** Internal Builder is used for build               ****
g++ -O0 -g3 -Wall -c -fmessage-length=0 -omain.o ..\main.cpp
In file included from ..\main.cpp:8:
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h: In instantiation of `std::back_insert_iterator<vec<char> >':
..\str.h:25:   instantiated from here
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h:363: error: no type named `const_reference' in `class vec<char>'
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h: In function `_OutputIterator std::__copy(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = const char*, _OutputIterator = std::back_insert_iterator<vec<char> >]':
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:273:   instantiated from `_OutputIterator std::__copy_aux2(_InputIterator, _InputIterator, _OutputIterator, __true_type) [with _InputIterator = const char*, _OutputIterator = std::back_insert_iterator<vec<char> >]'
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:308:   instantiated from `_OutputIterator std::__copy_ni2(_InputIterator, _InputIterator, _OutputIterator, __false_type) [with _InputIterator = const char*, _OutputIterator = std::back_insert_iterator<vec<char> >]'
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:327:   instantiated from `_OutputIterator std::__copy_ni1(_InputIterator, _InputIterator, _OutputIterator, __false_type) [with _InputIterator = const char*, _OutputIterator = std::back_insert_iterator<vec<char> >]'
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:358:   instantiated from `_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = const char*, _OutputIterator = std::back_insert_iterator<vec<char> >]'
..\str.h:25:   instantiated from here
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_algobase.h:247: error: no match for 'operator=' in '(&__result)->std::back_insert_iterator<_Container>::operator* [with _Container = vec<char>]() = *__first'
C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h:338: note: candidates are: std::back_insert_iterator<vec<char> >& std::back_insert_iterator<vec<char> >::operator=(const std::back_insert_iterator<vec<char> >&)
Build error occurred, build is stopped
Time consumed: 505  ms.
potete darmi una mano nel capire dove è il problema?

9 Risposte

  • Re: [RISOLTO][C++]Problemi con back_inserter

    Premesso che ho compilato con VC++2010, nella classe vec mancano due typedef richiesti dalla libreria standard.
    
    	  typedef const T& const_reference;
    	  typedef T value_type;
    
  • Re: [RISOLTO][C++]Problemi con back_inserter

    Un errore lo noto quì io:
    
    //const char * charset
    std::copy(charset,charset+std::strlen(charset),std::back_inserter(data));
    
    tu stai cercando di ampliare un puntatore const mediante std::copy. poi il back_inserter dovrebbe funzionare su variabili dello stesso tipo. tu hai un (const) puntatore a char e li vuoi far appendere un vector<char>.

    sul template non capisco la classe it. Forse indendevi un iterator alla classe vedendo dopo che hai it begin e it end ma com'è definito non è un iteratore ma una classe. Lascio la parola cmq ai + esperti nel campo dei template.

    Nella classe vec non vedo l'implementazione dell'operatore =. C'è come dichiarazione ma non come implementazione nel file cpp.
  • Re: [RISOLTO][C++]Problemi con back_inserter

    No, il puntatore charset non viene modificato. std::copy si limita a fare una scansione tra due iteratori in input (in questo caso &charset[0] e &charset[strlen(charset)]) e mettere il risultato nell'iteratore prodotto da std::back_inserter (che in questo caso vuole un char visto che data è definito come vec<char>).

    Il secondo template invece è solo una semplificazione di std::copy, utile nel caso si abbiano iteratori provenienti da altri container.
    Es.
    
    std::string test = "ciao mondo";
    str s(test.begin(),test.end());
    
  • Re: [RISOLTO][C++]Problemi con back_inserter

    Su vc++ 2010 da dei warning ma il programma si compila e funzia. Viene chiamato la funzione create di vec e poi basta. A fine programma viene interpellato il dtor del vec che chiama uncreate().Qual'è il tuo problema.
  • Re: [RISOLTO][C++]Problemi con back_inserter

    shodan ha scritto:


    Premesso che ho compilato con VC++2010, nella classe vec mancano due typedef richiesti dalla libreria standard.
    
    	  typedef const T& const_reference;
    	  typedef T value_type;
    
    questo non lo sapevo

    io l'ho compilato con eclipse c++ , o meglio, lui non me lo fa compilare. quindi con Visual C++ compila senza lagne?

    EDIT:
    l'operatore = è la penultima funzione del file cpp
  • Re: [RISOLTO][C++]Problemi con back_inserter

    Con i due typedef postati: si.
    
    C:/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h:363: error: no type named 
    `const_reference' 
    in `class vec<char>'
    Il compilatore si aspetta quel const_reference (ho spezzato il messaggio per evidenziarlo), quindi lo devi dichiarare. Il value_type l'ho messo perché l'implementazione lo richiede, ma in genere si mette sempre operando con template perché può essere richiesto in altri algoritmi.
    Di solito si mette:
    
    typedef T value_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    // altri typedef
    
    Se noti hai pure messo:
    
    typedef vec<char>::size_type size_type;
    
    nella class str. Nulla vieta di complementare la cosa.
    
    class str{
      public:
         typedef vec<char>::value_type value_type;
         typedef vec<char>::pointer pointer;
         // etc.
       typedef vec<char>::size_type size_type;
    
  • Re: [RISOLTO][C++]Problemi con back_inserter

    Sei un piccolo grande genio! con quei typedef in più compila senza problemi. Grazie davvero, non sai quanto ci ho sbattuto la testa.
    Per curiosità come fai a sapere che proprio quei typedef sono essenziali per l'implementazione? io nelle reference c++ non ho trovato neinte.
  • Re: [RISOLTO][C++]Problemi con back_inserter

    Un pò perché ci si sbatte il naso, ma soprattutto perché sono definiti dallo standard.
    http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2010/n3126.pdf
    Sezione 21.4 del draft, 23.2 e 23.4.1
    Seguendo quelle direttive si ha la garanzia che i container autoprodotti sono compatibili STL.
  • Re: [RISOLTO][C++]Problemi con back_inserter

    Pdf salvato
    Grazie ancora.
Devi accedere o registrarti per scrivere nel forum
9 risposte