Benutzerdefinierte Manipulatoren für vector



  • Hi,

    ich möchte Manipulatoren definieren, so dass ich Objekte meiner Klassen auf verschiedenen Detailstufen mittels des <<-Operators ausgeben kann. Also z.B. eine Klasse Hook_Position entweder als

    id: 0
    age: 4.5
    relative_age: 4.5
    non_rec_suc: 0
    suc: 4
    idx_in_suc: 0
    
    mut_rate: 0
                0         1         2         3
    A      0.6616    0.6616    0.1128    0.1128
    C      0.1128    0.1128    0.6616    0.6616
    G      0.1128    0.1128    0.1128    0.1128
    T      0.1128    0.1128    0.1128    0.1128
    

    oder als

    id: 0
    

    Das habe ich (mich am Stroustrup orientierend) mittels der Klassentemplates

    template<class T> class Base_Form
    {
    	friend std::ostream& ::operator<<<>(std::ostream& s, const Base_Bound_Form<T>& bf);
    private:
    	unsigned m_level;   // Detailgrad
    public:
    	Base_Form(unsigned level) : m_level(level) { }
    	Base_Bound_Form<T> operator()(const T* n) const { return Base_Bound_Form<T>(*this, n); }
    	unsigned level() const { return m_level; }
    };
    
    template<class T> class Base_Bound_Form
    {
    private:
    	const Base_Form<T>& m_form;
    	const T* m_data;
    public:
    	Base_Bound_Form(const Base_Form<T>& form, const T* data) : m_form(form), m_data(data) { }
    	const Base_Form<T>& form() const { return m_form; }
    	const T* data() const { return m_data; }
    };
    

    gemacht. Der <<-Operator für Base_Bound_Form<Hook_Position> ist wie folgt definiert (Details sind irrelevant):

    template<> std::ostream& operator<<(std::ostream& s, const Base_Bound_Form<Hook_Position>& bf)
    {
    	bf.form().level();
    	unsigned level = bf.form().level();
    	const Hook_Position* hp = bf.data();
    
    	switch (level) {
    	case 0:
    		s << hp->ID << endl;
    		break;
    	default:
    		s << "id: " << hp->ID << endl;
    		s << "age: " << hp->m_age << endl;
    		s << "relative_age: " << hp->relative_age() << endl;
    		s << "non_rec_suc: " << hp->m_non_rec_suc->name() << endl;
    		s << "suc: " << hp->m_suc->name() << endl;
    		s << "idx_in_suc: " << hp->m_idx_in_suc << endl << endl;
    		if (Prob_Nd* n = dynamic_cast<Prob_Nd*>(hp->non_rec_suc())) {
    			Base_NNP* probs = n->probs(type<Base_NNP>());
    			for (unsigned mr = 0; mr < hp->tree()->num_mutation_rates(); ++mr) {
    				s << "mut_rate: " << mr << endl;
    				s << "   ";
    				for (unsigned site = 0; site < hp->non_rec_suc()->num_sites(); ++site) {
    					s << format("%10d") % site;
    				}
    				s << endl;
    				for (unsigned nucl = 0; nucl < NUM_NUCL; ++nucl) {
    					s << Constants::alphabet().character(nucl) << "  ";
    					for (unsigned site = 0; site < hp->non_rec_suc()->num_sites(); ++site) {
    						double p = probs->lnp_at_hook_position(hp->m_idx_in_suc,
    								site, mr, nucl);
    						s << format("%10.4f") % exp(p);
    					}
    					s << endl;
    				}
    
    			}
    		}
    		else
    			throw ERROR(logger, "not implemented");
    		break;
    	}
    
    	return s;
    }
    

    Die Ausgabe erfolgt mittels

    Hook_Position hp = ...;
    cout << Base_Bound_Form<Hook_Position>(Base_Form<Hook_Position>(0), &hp) << endl;
    

    Das läuft alles soweit wie es soll, aber nun würde ich das Ganze gerne erweitern, so dass ich auch einen vector<Hook_Position> ausgeben und den Detailgrad auch mittels Manipulatoren festlegen kann.

    Hat jemand eine Idee, wie man das am besten macht?


Anmelden zum Antworten