2016-05-16 34 views
7

Więc jeśli mam coś takiegowyjście Przeciążenie operator << dla klasy wydrukować krotki środku

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

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

chcę przeciążać operatora < < tak, że będzie rekurencyjnie wydrukować krotki po wezwaniu klasa.

np.

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

miejmy nadzieję wydrukować „123”

Widziałem inne przykłady drukarek krotka ale nie może zastosować go do mojej klasy, bez konieczności pęczek kłopoty

Chyba powinienem zacząć funkcję jak element ten

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

i następnie rzeczywistej funkcji poza klasy

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

To zadziałało, gdy zadzwonię do operatora < < na mojej klasie. Ale nie mam pojęcia, jak sprawić, by faktycznie wydrukował krotkę.

Każda pomoc będzie mile widziane

+1

Musisz rekurencyjnie rozwinąć szablon variadic poprzez częściową specjalizację. Zobacz [to pytanie] (http://stackoverflow.com/questions/7124969/recursive-variadic-template-to-print-out-the-contents-of-a-parameter-pack). – denniskb

Odpowiedz

2

Aby zbudować rozwiązanie użyłem krotki kod drukowania z cppreference wspomniano tutaj this. Reszta kodu to klej, który utrzymuje wszystko razem. Here Położyłem próbkę roboczą.

#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

Dzięki za odpowiedź, gdy próbuję tego, otrzymuję 2 błędy: błąd: nie można powiązać std :: ostream {aka std :: basic_ostream } 'lwartość na' std :: basic_ostream && 'os << std::get<0> (t); i błąd: brak zgodności dla "operatora <<" (typami argumentów są "std :: ostream {aka std :: basic_ostream }" i "std :: __ tuple_element_t <0ul, – user2770808

+0

Czy możesz podać mi swoją dokładną wersję kompilatora, a także kompilator oznaczony flagą, zostanie użyty? – tomekpe

+0

Naprawiłem to ze względu na sposób, w jaki budowałem swoją krotkę. – user2770808

0

Jeśli możesz zrobić bez standardowych krotek, proponuję następujące proste (mam nadzieję) rozwiązanie.

#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; 
}