1 Востаннє редагувалося Yola (26.06.2015 13:31:06)

Тема: У циклі або рекурсивно вивести вміст tuple.

Якщо маємо

auto t = make_tuple(1, 3, 5.3, 't', "sdfasfd");

Як у циклі або рекурсивно вивести її в cout.

Мій варіант:

Прихований текст
template <int N, class T>
struct RecursiveLoop
{
    void operator () (T t)
    {
        RecursiveLoop<N - 1, decltype(t)> rl;
        rl(t);

        cout << get<N - 1>(t) << endl;
    }
};

template <class T>
struct RecursiveLoop<0, T>
{
    void operator () (T)
    {
        return;
    }
};

...
    auto t = make_tuple(1, 3, 5.3, 't', "sdfasfd");
    RecursiveLoop<tuple_size<decltype(t)>::value, decltype(t)> rl;
    rl(t);

2

Re: У циклі або рекурсивно вивести вміст tuple.

Обхід кортежу виглядає як збочення, що в циклі, що рекурсивно.

3

Re: У циклі або рекурсивно вивести вміст tuple.

quez написав:

Обхід кортежу виглядає як збочення, що в циклі, що рекурсивно.

Під час зневадження іноді потрібно  :)

4

Re: У циклі або рекурсивно вивести вміст tuple.

Чому тоді не виводити поелементно? Що там у вас за кортежі такі?

5 Востаннє редагувалося Yola (26.06.2015 13:55:04)

Re: У циклі або рекурсивно вивести вміст tuple.

quez написав:

Чому тоді не виводити поелементно? Що там у вас за кортежі такі?

Чуєш легеньочку, або пиши відповідь, або котись під три чорти!  >:o

6

Re: У циклі або рекурсивно вивести вміст tuple.

Це рекурсивнозалуплений код на вас так подіяв?

Подякували: koala1

7

Re: У циклі або рекурсивно вивести вміст tuple.

Yola написав:
quez написав:

Чому тоді не виводити поелементно? Що там у вас за кортежі такі?

Чуєш легеньочку, або пиши відповідь, або котись під три чорти!  >:o

Отаким відповідати точно не хочу.

8

Re: У циклі або рекурсивно вивести вміст tuple.

Yola написав:

Якщо маємо

auto t = make_tuple(1, 3, 5.3, 't', "sdfasfd");

Як у циклі або рекурсивно вивести її в cout.

Мій варіант:

Прихований текст
template <int N, class T>
struct RecursiveLoop
{
    void operator () (T t)
    {
        RecursiveLoop<N - 1, decltype(t)> rl;
        rl(t);

        cout << get<N - 1>(t) << endl;
    }
};

template <class T>
struct RecursiveLoop<0, T>
{
    void operator () (T)
    {
        return;
    }
};

...
    auto t = make_tuple(1, 3, 5.3, 't', "sdfasfd");
    RecursiveLoop<tuple_size<decltype(t)>::value, decltype(t)> rl;
    rl(t);

За такий код треба гнати під три чорти. І іншим заборонити згадувати.

9

Re: У циклі або рекурсивно вивести вміст tuple.

mich_retten написав:

За такий код треба гнати під три чорти. І іншим заборонити згадувати.

Конструктивненько...
Ви в стані написати кращий? Чи хоча б вказати на вади цього?

10

Re: У циклі або рекурсивно вивести вміст tuple.

Ваш код - це приклад того, як можна відносно просту задачу вирішити таким "ажурним" способом, що сам автор не може збагнути, як це все функціонує.
Добра практика - це коли відносно складну задачу вирішують відносно простим способом.
А Ваш код - для тих, кому свербить спробувати гвіздка забити не за допомогою молотка, а використати щойно придбаний пристрій. Він, правда, зовсім для інших цілей зроблений, але зараз треба забити гвіздок, і під рукою як раз цей чудо-пристрій. Хто може зробити краще?
Програмоїдів з такими замашками - закреслити раз і назавжди!

11 Востаннє редагувалося P.Y. (27.06.2015 06:25:17)

Re: У циклі або рекурсивно вивести вміст tuple.

Все ж хотілось би почути критику коду окремо від критики манери ведення дискусії автора цього коду. У чому його неймовірна складність — також не помітив.

Я знаю С++ не настільки глибоко, щоб бачити явні недоліки. А втім, елементом кортежа також може бути кортеж (який сам по собі не годиться для виводу)? Тоді такий спосіб не спрацює...

Подякували: Yola1

12

Re: У циклі або рекурсивно вивести вміст tuple.

Наприклад, перевизначення оператора () для непритаманної йому операції.

13

Re: У циклі або рекурсивно вивести вміст tuple.

quez написав:

Наприклад, перевизначення оператора () для непритаманної йому операції.

А які операції притаманні оператору () ?

Щоб не затягувати обговорення додам, що це просто функтор, він може робити будь-що.

14

Re: У циклі або рекурсивно вивести вміст tuple.

P.Y. написав:

Все ж хотілось би почути критику коду окремо від критики манери ведення дискусії автора цього коду. У чому його неймовірна складність — також не помітив.

Я знаю С++ не настільки глибоко, щоб бачити явні недоліки. А втім, елементом кортежа також може бути кортеж (який сам по собі не годиться для виводу)? Тоді такий спосіб не спрацює...

Можна перевантажити operator<< для кортежу:

#include <iostream>
#include <tuple>
#include <type_traits>
using namespace std;

template<size_t Size, typename... Args>
typename enable_if<Size == 0, void>::type tuple_print_hlp(ostream& ostr, const tuple<Args...>& t)
{}

template<size_t Size, typename... Args>
typename enable_if<(Size > 0), void>::type tuple_print_hlp(ostream& ostr, const tuple<Args...>& t)
{
    tuple_print_hlp<Size - 1>(ostr, t);
    cout << get<Size - 1>(t) << endl;
}

template<size_t Size, typename... Args>
typename enable_if<Size == 0, void>::type tuple_print(ostream& ostr, const tuple<Args...>& t)
{}

template<size_t Size, typename... Args>
typename enable_if<(Size > 0), void>::type tuple_print(ostream& ostr, const tuple<Args...>& t)
{
    tuple_print_hlp<Size - 1>(ostr, t);
    cout << get<Size - 1>(t); // Останній елемент виводимо саме тут для того, щоб не виводити зайвого endl
}

template<typename... Args>
ostream& operator<<(ostream& ostr, const tuple<Args...>& t)
{
    tuple_print<tuple_size<tuple<Args...> >::value>(ostr, t);
    return ostr;
}

int main(void)
{
    auto t = make_tuple(1, 3, make_tuple(5.3, "gtewtg"), 't', make_tuple("sdfasfd", 234, 56.75));
    cout << t << endl;
    return 0;
}
Подякували: Yola, P.Y., Дмитро-Чебурашка4

15

Re: У циклі або рекурсивно вивести вміст tuple.

Мені подобається! Cool!

16

Re: У циклі або рекурсивно вивести вміст tuple.

Трюк з індексами плюс розширення пакована шаблонних параметрів.

//фактично оце
f(h(args)...);
//розширюється до цього
f(h(E1), h(E2), h(E3), ...)
// E1..En - аргументи у варіадичному шаблоні

ось іще

f(h(args...) + args...);
f(h(E1,E2,E3) + E1, h(E1,E2,E3) + E2, h(E1,E2,E3) + E3)

І сам жахастик :)

// **********************************************************************************************
template <size_t... Is>
struct indices {};

template <size_t N, size_t... Is>
struct build_indices : build_indices<N - 1, N - 1, Is...> {};

template <size_t... Is>
struct build_indices<0, Is...> : indices<Is...>{};

template <typename Tuple>
using IndicesFor = build_indices<tuple_size<Tuple>::value>;

// **********************************************************************************************
template <typename T>
struct is_tuple : false_type {};

template <typename... T>
struct is_tuple<tuple<T...>> : true_type{};

// **********************************************************************************************
// Порожня
void printImpl(char) {}

template <typename Tuple, typename ..._Vals, 
    typename enable_if<is_tuple<typename decay<Tuple>::type>::value>::type* = nullptr> //SFINAE
void printImpl(int, Tuple&& t, _Vals... _vals)
{
    print_tuple(forward<typename decay<Tuple>::type>(t));
    after_print(_vals...);
}

template <typename _First, typename ..._Vals>
void printImpl(char, _First&& first, _Vals... _vals)
{
    cout << first;
    after_print(_vals...);
}

// **********************************************************************************************
template <typename ..._Vals>
void after_print(_Vals... _vals)
{
    cout << " ";
    printImpl(0, _vals...);
}

void after_print() {}

// **********************************************************************************************
template <typename T, size_t... Is>
void print_tuple2(T&& t, indices<Is...>)
{
    // 0 ближче до int ніж до char
    printImpl(0, get<Is>(forward<T>(t))...);
}

// **********************************************************************************************
template <typename T>
void print_tuple(T&& t)
{
    cout << "{";
    print_tuple2(forward<T>(t), IndicesFor<T> {});
    cout << "}";
}

// **********************************************************************************************
// **********************************************************************************************
    // rvalues
    print_tuple(make_tuple(make_tuple(1, 2, "start_tuple"), 17, 'q', make_tuple("stop_tuple", 123)));
    cout << endl;

    // lvalue
    int i = 0;
    auto t = make_tuple();
    print_tuple(make_tuple(i, t));
    cout << endl;