2016-05-16 33 views
7

Quindi, se ho qualcosa di simileuscita Sovraccarico << operatore per una classe per stampare la tupla all'interno

template<typename... Args > 
class tuple_class 
{ 
    public: 
    std::tuple<Args...> tup; 

/*I left out the other functions */ 
}; 

voglio sovraccaricare l'operatore < < in modo che in modo ricorsivo stampare la tupla quando viene chiamato su la classe.

ex.

auto a = tuple_class(1, 2 ,3); 
std::cout << a << endl; 

si spera stampare '123'

Ho visto altri esempi di stampanti tuple ma non posso applicarlo alla mia classe senza avere un mucchio di guai

penso che dovrei iniziare con una funzione membro simili

template<typename... Args> 
    friend std::ostream& operator<<(std::ostream& os, const my_tuple<Args...> &m); 

e quindi la funzione effettiva all'esterno della classe

template<typename... Args> 
std::ostream& operator<<(std::ostream& os, const my_tuple<Args...> &m) 
{ 
    os << "SOMETHING" << std::endl; 
    return os; 
} 

che in realtà funzionava quando chiamo l'operatore < < sulla mia classe. Ma non ho idea di come fare in realtà stampare la tupla.

Qualsiasi aiuto sarebbe apprezzato

+1

È necessario srotolare ricorsivamente il modello variadic attraverso una specializzazione parziale. Vedi [questa domanda] (http://stackoverflow.com/questions/7124969/recursive-variadic-template-to-print-out-the-contents-of-a-parameter-pack). – denniskb

risposta

2

Per costruire una soluzione che ho usato tuple codice di stampa da cppreference qui menzionato this. Il resto del codice è colla per tenere insieme le cose. Here Metto campione funzionante.

#include <tuple> 
#include <iostream> 
#include <string> 

// tuple printer 
template<class Tuple, std::size_t N> 
struct TuplePrinter { 
    static std::ostream& print(std::ostream& os, const Tuple& t) 
    { 
     TuplePrinter<Tuple, N - 1>::print(os, t); 
     os << ", " << std::get<N - 1>(t); 
     return os; 
    } 
}; 

template<class Tuple> 
struct TuplePrinter<Tuple, 1> { 
    static std::ostream& print(std::ostream& os, const Tuple& t) 
    { 
     os << std::get<0>(t); 
     return os; 
    } 
}; 

template<class... Args> 
std::ostream& print(std::ostream& os, const std::tuple<Args...>& t) 
{ 
    os << "("; 
    TuplePrinter<decltype(t), sizeof...(Args)>::print(os, t); 
    os << ")\n"; 
    return os; 
} 


// class to keep tuple inside 
template<typename... Args> 
class tuple_class { 
    template<typename... Args2> 
    friend std::ostream& operator<<(std::ostream& os, const tuple_class<Args2...> &m); 

    std::tuple<Args...> tup; 
public: 
    tuple_class(Args&&... args) : tup(std::forward<Args>(args)...) { 

    } 
}; 

// usage of the printer 
template<typename... Args> 
std::ostream& operator<<(std::ostream& os, const tuple_class<Args...> &m) { 
    print(os, m.tup); 
    return os; 
} 



int main() { 
    tuple_class<int,float,std::string> tc(1,3.0f,"string"); 
    std::cout << tc; 
    return 0; 
} 
+0

Grazie per la risposta, quando provo questo ottengo 2 errori: errore: impossibile legare 'std :: ostream {aka std :: basic_ostream }' lvalue a 'std :: basic_ostream &&' os << std::get<0> (t); e l'errore: non è partita per 'operatore <<' (tipi di operando sono 'std :: ostream {alias std :: basic_ostream }' e 'std :: __ tuple_element_t <0ul, – user2770808

+0

mi può fornire la versione esatta del compilatore e anche compilatore ti contrassegna, usa? – tomekpe

+0

Ho risolto il problema con il modo in cui stavo costruendo la mia tupla. Grazie! – user2770808

0

Se si può fare senza tuple standard, propongo la seguente semplice soluzione (lo spero).

#include <iostream> 

template <typename ... Args > 
class my_tuple; 

template <typename A0, typename ... Args > 
class my_tuple<A0, Args...> 
{ 
    private: 

     A0     elem; 
     my_tuple<Args...> next; 

    public: 

     my_tuple (const A0 & a0, const Args & ... args) 
     : elem { a0 }, next { args ... } 
     { } 

     /*I left out the other functions */ 

     friend std::ostream& operator<< (std::ostream & os, 
             const my_tuple<A0, Args...> & m) 
     { return os << m.elem << m.next; } 
}; 

template <> 
class my_tuple<> 
{ 
    public: 

     friend std::ostream& operator<< (std::ostream & os, 
             const my_tuple<> &) 
     { return os; } 
}; 

int main() 
{ 
    my_tuple<int, float, long> mt1 { 12, 23.4, 45L }; 
    my_tuple<int, int, int>  mt2 { 1, 2, 3 }; 

    std::cout << "my tuple 1 [" << mt1 << ']' << std::endl; 
    std::cout << "my tuple 2 [" << mt2 << ']' << std::endl; 

    return 0; 
}