Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 24, средняя оценка - 4.71
Pure
228 / 49 / 2
Регистрация: 13.03.2012
Сообщений: 453
Записей в блоге: 7
#1

Переменное число аргументов - C++

14.08.2012, 14:11. Просмотров 3049. Ответов 32
Метки нет (Все метки)

РАСПАКОВКА
есть ли способы кроме рекурсии и передачи как списка инициализации?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.08.2012, 14:11
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Переменное число аргументов (C++):

Переменное число аргументов - C++
Есть такой код. Хочу сделать, чтобы operator() принимал переменное число аргументов переменных типов. Т.е. передаём template<int,...

Переменное количество аргументов в функции ( зацикливание ) - C++
Здравствуйте. Подскажите пожалуйста как правильно огранизировать доступ к каждому параметру. Заранее спасибо. Вот код: #include...

Программа должна читать из консоли переменное количество аргументов и выводить их - C++
Программа должна читать переменное кол-во аргументов из командной строки и выводить их в виде "Hello, arg!" . Ф-я main() принимает два...

Переменное число параметров шаблона - C++
Здоровеньки булы. Не уверен, что название темы точно отражает суть вопроса. Есть заготовка шаблонного делегата, параметры которого -...

Переменное число параметров функции - трабл с int - C++
Функция - выводит среднее арифметическое своих аргументов. Рабочий пример с double: #include <cstdarg> #include <iostream> double...

Есть функция с кучей аргументов, как её вызвать в другой функции (если половины аргументов у меня нет)? - C++
Я конечно, понимаю, что на такие вопросы отвечают "почитай книжку". Я читала, честное слово:) Конкретно. Есть функция void jacobi (...

32
Pure
228 / 49 / 2
Регистрация: 13.03.2012
Сообщений: 453
Записей в блоге: 7
15.08.2012, 09:18  [ТС] #16
Цитата Сообщение от alex_x_x Посмотреть сообщение
те то что у тебя в AS3 написано ближе к std::vector<boost::any>, чем к tuple'ам
интересовало не сравнение как таковое меж статическими и динамическими кортежами
Меня заинтересовала сама возможность удобной обработки переменного количества аргументов. поскольку функции (...)есть уже давно, а тут вдруг появилось (...Args). Т.е. интересовала сама возможность. Что мешает в ++ сделать function (...Args)? и дать возможность извлекать аргументы без всяких va_list, а работая со встроенным типом ...Arg. Думаю это дело вероятного будущего поскольку например auto не постеснялись ввести и прочие вещи развивающие... удобный интерфейс для пользователя)

-=ЮрА=-, надо сделать нечто вроде такого
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <locale>
 
void consume_done (...Args)
{
Args[0](Args[1]);
}
 
int main()
{
consume_done([](const char* a){setlocale(LC_ALL,"RUS");std::cout<<a\n;}, "Юра данит");
}
давай вынесем твои поиски в этом направлении в твой блог
0
Изображения
 
Pure
228 / 49 / 2
Регистрация: 13.03.2012
Сообщений: 453
Записей в блоге: 7
15.08.2012, 09:23  [ТС] #17
~OhMyGodSoLong~, приятно..
0
alex_x_x
бжни
2454 / 1659 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
15.08.2012, 10:55 #18
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <tuple>
 
template<class... Args>
void consume_done (Args... args)
{
   std::tuple<Args...> tuple{args...};
   std::get<0>(tuple)(std::get<1>(tuple));
}
 
int main()
{
   consume_done ([](const char* a){
                    std::cout<< a << std::endl;
                 }, "Юра данит");
}
0
Pure
228 / 49 / 2
Регистрация: 13.03.2012
Сообщений: 453
Записей в блоге: 7
15.08.2012, 11:44  [ТС] #19
alex_x_x, ишь ты подишьты, какой упрямы алекс.
это мой косяк. условие не раскрываюшее прелести стандарта. тут этот огород не нужен.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
void consume_done (void(*p)(const char*),const char* n)
{
   p(n);
}
 
int main()
{
   consume_done ([](const char* a){
                    std::cout<< a << std::endl;
                 }, "Юра данит");
}

попробую сформулировать запрос получше. вейт ми

Добавлено через 26 минут
alex_x_x, ладно сдаюсь, кроме требования константы в std::get<> придраться особо не к чему.
т.е. если будет 10 элементов тупла, и все они нужны то потребуется 10 раз писать get.

ю вин.
0
OhMyGodSoLong
~ Эврика! ~
1245 / 994 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
15.08.2012, 12:14 #20
Хотя мне тоже не особо понятно, зачем вариадические темплейты сделали такими. Хотя, в принципе, догадываюсь: итеративный интерфейс обработки вариадических параметров потребовал бы
  • или перепиливания всего интерфейса вызова функций, чтобы они при вызове таскали с собой типы и их количество;
  • или же сделал бы возможными обращения ко всяким сотым аргументам, когда фактически передано три (это ваш get<> с переменной) — а это ломает напрочь исходную задумку сделать это хоть сколь-нибудь безопаснее обычных va_list.

Если вам надо передать динамическое количество динамически типизированных аргументов в функцию, то есть проверенный временем способ: затолкайте их в коллекцию и передайте эту коллекцию. std::vector<boost::any> в 200 раз понятнее этой шаблонной магии (да, магия внутри буста, но она хотя бы документирована). Да, конечно, что-нибудь вроде
C++
1
2
3
func(1, 2, 3, VA(4, "5", Object(6, 7, 8)));
// ...
void func(int a, int b, double c, const VarargsVector &varargs) { ... }
выглядит не так круто как
C++
1
2
3
func(1, 2, 3, 4, "5", Object(6, 7, 8));
// ...
void func(int a, int b, double c, Types... varargs) { ... }
Но это хотя бы работает везде (я напомню, что та же Студия вообще не поддерживает полиадические темплейты).

А ещё бонусом этот вариант даёт возможность собирать список аргументов в рантайме. Темплейты при всей своей крутизне такого никогда не смогут.
1
ForEveR
В астрале
Эксперт С++
7992 / 4751 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.08.2012, 12:59 #21
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Pure, Как вариант.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include <tuple>
#include <iostream>
 
template<typename T>
struct func
{
   func(const T& t):
      seq(t)
   {
   }
   template<typename U>
   void operator () (const U&)
   {
      std::cout << std::get<U::value>(seq) << std::endl;
   }
   T seq;
};
 
int main()
{
   auto t = std::make_tuple(1, 2, "hello", 5.6);
   boost::mpl::range_c<int, 0, std::tuple_size<decltype(t)>::value> range;
   boost::mpl::for_each<decltype(range)>(func<decltype(t)>(t));
}
Можно и не писать функтор, но что-то я плохо дружу с бустовскими лямбдами(

Добавлено через 41 минуту
~OhMyGodSoLong~, Это все хорошо, но boost::any довольно неудобен в использовании, все-таки any_cast постоянно юзать не очень радует + это все-таки абсолютно разные вещи, std::vector<boost::any> вектор объектов, в то время как T... раскрывается в типы напрямую, то есть такое с any не напишешь

C++
1
2
3
4
5
6
7
8
9
10
11
template<typename T, class... Args>
std::vector<T> create_vector(const Args&... args)
{
    return std::vector<T>(args...);
}
 
int main()
{
    const auto& v1 = create_vector<int>(5);
    const auto& v2 = create_vector<int>(5, 4);
}
А чтобы сделать так, чтобы аргументы хранились как ты сказал и удобно использовались нужна рефлексия
4
-=ЮрА=-
15.08.2012, 13:30
  #22

Не по теме:

Цитата Сообщение от Pure Посмотреть сообщение
давай вынесем твои поиски в этом направлении в твой блог
А Смысл?Я всего лишь написал вчера предположительную реализацию по твоему заданию (верней как понял его да ещё и без VA , сам же я стороник cstdarg). Будет время подумаю ещё...

0
Pure
228 / 49 / 2
Регистрация: 13.03.2012
Сообщений: 453
Записей в блоге: 7
15.08.2012, 13:44  [ТС] #23
ForEveR, т.е. итоговое решение выглядит так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include <tuple>
#include <iostream>
 
template<typename T>
struct func
{
   func(const T& t):
      seq(t)
   {
   }
   template<typename U>
   void operator () (const U&)
   {
      std::cout << std::get<U::value>(seq) << std::endl;
   }
   T seq;
};
 
 
template<class... Args>
void consume_done (Args... args)
{
   std::tuple<Args...> t{args...};
    boost::mpl::range_c<int, 0, std::tuple_size<decltype(t)>::value> range;
   boost::mpl::for_each<decltype(range)>(func<decltype(t)>(t));
  
} 
int main()
{  
  consume_done("5555",6.7,'Z',67);  
}
чтож, некрасиво выглядит, но работает. спасибо за то что потратил время и поморочился.

луета конечно какая то. перепаковка тупла в рендж. скрестили бы сразу и то и другое в стандарте.
0
OhMyGodSoLong
~ Эврика! ~
1245 / 994 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
15.08.2012, 13:53 #24
ForEveR, я и не говорил, что оно замена статическому варианту. Ваш вариант для Pure сломается же ещё на стадии компиляции, если в кортеж засунуть что-то, что ostream не умеет выводить. Для полного счастья ещё бы отделить сам функтор от вот этого T seq;, но что-то у меня пока не выходит.

Для удобной динамической типизации надо рефлексию, а в Си++ её нет и не будет, пока темлейты будут кушаться при компиляции. Ну и, естественно, это потребует переделывать механику вызова функций.

Ну, и это только подтверждает, что за этими всеми плюшками надо идти в динамические языки. Или в Хаскелл — у него выводилка типов достаточно умная.
1
ForEveR
В астрале
Эксперт С++
7992 / 4751 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.08.2012, 15:19 #25
Pure, Ну тут нет перепаковки. Рейндж используется исключительно для индексов.
~OhMyGodSoLong~, Ну да. Слом на этапе компиляции - это не так уж и плохо. Можно конечно SFINAE задействовать как-нибудь... Ща поковыряюсь ради интереса. Ну рефлексию-то очень даже предлагают ввести (говорил Страуструп что-то на эту тему). А так конечно с динамическими языками не сравнится.

Добавлено через 1 час 25 минут
Ну как-то так, но не сомневаюсь что можно и проще.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include <tuple>
#include <iostream>
 
template<typename T, size_t Idx, typename Enabled = void>
struct is_printable
{
   static constexpr bool value = false;
};
 
template<typename T, size_t Idx>
struct is_printable<T, Idx,
   typename std::enable_if<std::is_lvalue_reference<decltype(std::cout << std::get<Idx>(T()))>::value>::type>
{
   static constexpr bool value = true;
};
 
template<typename T>
struct func
{
   func(const T& arg):
      seq(arg)
   {
   }
 
   template<typename U, typename Enabled = void>
   struct func_impl
   {
      template<typename Seq>
      static void apply(const Seq& seq) { }
   };
 
   template<typename U>
   struct func_impl<U, typename std::enable_if<is_printable<T, U::value>::value>::type>
   {
      template<typename Seq>
      static void apply(const Seq& seq) { std::cout << std::get<U::value>(seq) << std::endl; }
   };
 
   template<typename U>
   void operator () (const U&)
   {
      func_impl<U>::apply(seq);
   }
 
   T seq;
};
 
struct A
{
};
 
struct B
{
};
 
int main()
{
   auto t = std::make_tuple(A(), 1, 2, "hello", B(), 5.6);
   boost::mpl::range_c<int, 0, std::tuple_size<decltype(t)>::value> range;
   boost::mpl::for_each<decltype(range)>(func<decltype(t)>(t));
}
http://liveworkspace.org/code/6ecd7fd0277214d98c15e4b4bc39897b
0
Pure
228 / 49 / 2
Регистрация: 13.03.2012
Сообщений: 453
Записей в блоге: 7
15.08.2012, 15:52  [ТС] #26
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
хотя ерунда. сейчас опять. std::get<1> std::get<2>.

снимаю задачу.

из всего диалога какие выводы напросились.

1. если на этапе компиляции есть все исходные данные то работая std::get можно спокойно окучивать кортеж, который принял переменный список.
2. индексации по кортежу нормальной не было сделано. достаточно посмотреть монстрокод нужный для прохода. возникает вопрос а не зарыта ли глубоко в буст рекурсия? Если нет то что мешало сделать индексы кортежу.

будь мужиком ставь лайк
0
ForEveR
В астрале
Эксперт С++
7992 / 4751 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.08.2012, 16:16 #27
Pure, Зарыта конечно. Шаблонное метапрограммирование на С++ в любом случае сводится к рекурсивной раскрутке шаблонов.
for_each к примеру.
mpl::for_each
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
template< bool done = true >
struct for_each_impl
{
    template<
          typename Iterator
        , typename LastIterator
        , typename TransformFunc
        , typename F
        >
    static void execute(
          Iterator*
        , LastIterator*
        , TransformFunc*
        , F
        )
    {
    }
};
 
template<>
struct for_each_impl<false>
{
    template<
          typename Iterator
        , typename LastIterator
        , typename TransformFunc
        , typename F
        >
    static void execute(
          Iterator*
        , LastIterator*
        , TransformFunc* 
        , F f
        )
    {
        typedef typename deref<Iterator>::type item;
        typedef typename apply1<TransformFunc,item>::type arg;
    
        // dwa 2002/9/10 -- make sure not to invoke undefined behavior
        // when we pass arg.
        value_initialized<arg> x;
        aux::unwrap(f, 0)(boost::get(x));
        
        typedef typename mpl::next<Iterator>::type iter;
        for_each_impl<boost::is_same<iter,LastIterator>::value>
            ::execute( static_cast<iter*>(0), static_cast<LastIterator*>(0), static_cast<TransformFunc*>(0), f);
    }
};
 
} // namespace aux
 
// agurt, 17/mar/02: pointer default parameters are necessary to workaround 
// MSVC 6.5 function template signature's mangling bug
template<
      typename Sequence
    , typename TransformOp
    , typename F
    >
inline
void for_each(F f, Sequence* = 0, TransformOp* = 0)
{
    BOOST_MPL_ASSERT(( is_sequence<Sequence> ));
 
    typedef typename begin<Sequence>::type first;
    typedef typename end<Sequence>::type last;
 
    aux::for_each_impl< boost::is_same<first,last>::value >
        ::execute(static_cast<first*>(0), static_cast<last*>(0), static_cast<TransformOp*>(0), f);
}
 
template<
      typename Sequence
    , typename F
    >
inline
void for_each(F f, Sequence* = 0)
{
    for_each<Sequence, identity<> >(f);
}
0
alex_x_x
бжни
2454 / 1659 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
15.08.2012, 16:35 #28
Цитата Сообщение от Pure Посмотреть сообщение
2. индексации по кортежу нормальной не было сделано. достаточно посмотреть монстрокод нужный для прохода. возникает вопрос а не зарыта ли глубоко в буст рекурсия? Если нет то что мешало сделать индексы кортежу.
ты не понимаешь в чем разница в разборе динамических и статических кортежей
"обыкновенного" статического перебора кортежа просто не может быть
2
Pure
228 / 49 / 2
Регистрация: 13.03.2012
Сообщений: 453
Записей в блоге: 7
15.08.2012, 16:51  [ТС] #29
Цитата Сообщение от ForEveR Посмотреть сообщение
Pure, Зарыта конечно.
тогда в чем отличие от самого первого поста? столько строк и все напрасно-результат такой же
0
ForEveR
В астрале
Эксперт С++
7992 / 4751 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.08.2012, 16:51 #30
Pure, В том, что используются готовые алгоритмы. Нерекурсивных вариантов нет и быть не может.
0
15.08.2012, 16:51
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.08.2012, 16:51
Привет! Вот еще темы с ответами:

Разработать функцию, возвращающую сумму остатка от деления первого и второго аргументов на заданное число - C++
Разработать функцию типа int, что возвращает сумму остатка от деления первого и второго аргументов на 5, если сумма больше 20, иначе...

Написать функцию, которая получает в качестве аргументов целое положительное число и систему счисления - C++
Всем Здравствуйте, Дамы и Господа. Вот получил такое задание. но что-то вообще не понимаю. Написать функцию, которая получает в...

Составить функцию, принимающую переменное количество параметров - C++
Напишите и протестируйте шаблонную функцию с переменным числом аргументов sum_values(), которая принимает список произвольной длины с...

Можно ли в цикле for устанавливать переменное значение инициализатора? - C++
Ну вот мне позарез надо сделать так: int j=(23-posl); for (i=j;i&gt;=0;i--) cout &lt;&lt; c; так нельзя? а мне очень нужно. что можно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru