2016-05-16 2 views
7

Так что если у меня есть что-то вроде этогоПерегрузки выход << оператор класса для печати кортежа внутри

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

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

Я хочу, чтобы перегрузить оператор < < так, что он будет рекурсивно печатать кортеж при вызове на класс.

ex.

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

можно надеяться напечатать «123»

Ive видели другие примеры кортежей принтеров, но я не могу применить его к моему классу, не имея кучу неприятностей

Я думаю, что я должен начать с функция-член как этот

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

, а затем фактическая функция вне класса

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

Это действительно сработало, когда я вызываю оператор < < на мой класс. Но я понятия не имею, как заставить его на самом деле распечатать кортеж.

Любая помощь будет оценена

+1

Вам необходимо рекурсивно развернуть вариационный шаблон с помощью частичной специализации. См. [Этот вопрос] (http://stackoverflow.com/questions/7124969/recursive-variadic-template-to-print-out-the-contents-of-a-parameter-pack). – denniskb

ответ

2

Для построения решения я использовал кортеж код печати из cppreference упомянутого здесь this. Остальная часть кода - это клей, чтобы держать вещи вместе. Here Я положил рабочий образец.

#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

Спасибо за ответ, когда я попробую это, я получаю 2 ошибки: ошибка: невозможно привязать 'std :: ostream {aka std :: basic_ostream }' lvalue to 'std :: basic_ostream &&' os << std::get<0> (t); и ошибка: нет соответствия для «operator <<» (типы операндов: «std :: ostream {aka std :: basic_ostream }» и «std :: __ tuple_element_t <0ul, – user2770808

+0

Не могли бы вы предоставить мне свою точную версию компилятора, а также компилятор флагов вы используете? – tomekpe

+0

Я исправил, что это связано с тем, как я строю свой кортеж. Спасибо! – user2770808

0

Если вы можете обойтись без стандартных кортежей, я предлагаю следующее простое (я надеюсь, что такое) решение.

#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; 
} 
Смежные вопросы