Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.64/25: Рейтинг темы: голосов - 25, средняя оценка - 4.64
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
1

Инициализация std::tuple переменным числом аргументов

29.07.2013, 00:38. Показов 4701. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый вечер.
Мне нужно инициализировать объект std::tuple, который является членом некоторого другого шаблонного класса с переменным числом аргументов.
Есть такой код, который, естественно, не компилируется:
C++
1
2
3
4
5
6
7
template<typename...Arg>
struct Base
{
    Base() : NumElems(sizeof...(Arg)), mems(std::make_tuple(Arg...)){}//std::make_tuple(Arg...) - это то, что мне хотелось бы получить в результате)))
    std::tuple<Arg...> mems;
    int NumElems;
};
Предполагается, что Arg - это некоторый список объектов разных классов, которые нужно создать и запихнуть в tuple<Arg...> mems.
У меня есть два вопроса:
1. Собственно, по вышеприведенному коду - как реализовать добавление объектов из списка Args в кортеж?
Например:
C++
1
2
3
4
struct A{};
struct B{};
struct C{};
Base<A,B,C> obj;
Нужно, чтобы при инициализации obj создались три объекта типа A,B и C и добавились в член mems.
2. Есть ли какой-нибудь способ "обхода" пакета Arg наподобие массиву (в цикле, например)?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.07.2013, 00:38
Ответы с готовыми решениями:

Функции с переменным числом аргументов
на пример sum(2,56,515,-23.65,548)?

Функции с переменным числом аргументов
Ребята, подскажите пожалуйста, где можно обстоятельно и подробно прочитать про использовании в C++...

Шаблоны с переменным числом аргументов
Написал шаблон функции с переменным числом аргументов которая считает сумму своих аргументов....

Написать функцию с переменным числом аргументов
Помогите понять, что от меня хотят-то вообще. Мне нужно: объявить функции в соответствии с...

18
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
29.07.2013, 01:41 2
только для типов с constexpr конструтором
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
#include <iostream>
#include <tuple>
 
template<typename... Args>
struct default_tuple_creator;
 
template<class T, typename... Args>
struct default_tuple_creator<T, Args...>
{
    static constexpr std::tuple<T, Args...> value = std::tuple_cat(std::make_tuple(T()), default_tuple_creator<Args...>::value);
};
 
template<class T>
struct default_tuple_creator<T>
{
    static constexpr std::tuple<T> value = std::make_tuple(T());
};
 
template<typename... Args>
std::tuple<Args...> default_constructed_tuple()
{
    return default_tuple_creator<Args...>::value;
}
 
template<typename... Args>
struct Base
{
    Base() 
    : mems(default_constructed_tuple<Args...>())
    , NumElems(sizeof...(Args))
    {}
    
    std::tuple<Args...> mems;
    int NumElems;
};
 
struct A 
{ 
    int a;  
    
    constexpr A() : a(100) {}
};
 
struct B 
{
    int b;
    
    constexpr B() : b(50) {}
};
 
struct C 
{
    int c;
};
 
 
int main()
{
   Base<A, B, C> obj;
 
   std::cout << std::get<0>(obj.mems).a 
             << std::get<1>(obj.mems).b 
             << std::get<2>(obj.mems).c 
             << std::endl;
    
   return 0;
}
2
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 02:18  [ТС] 3
Jupiter, кстати, вот так тоже работает как оказалось:
C++
1
2
3
4
5
6
7
8
template<typename...Arg>
struct Prc
{
    Prc() : mems(std::make_tuple(Arg()...)){}
  
    std::tuple<Arg...> mems;
 
};
1
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
29.07.2013, 02:28 4
Цитата Сообщение от Gorillych Посмотреть сообщение
Нужно, чтобы при инициализации obj создались три объекта типа A,B и C и добавились в член mems.
Я, если честно, не понял, если написать
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<typename...Arg>
struct Base
{
    Base() : NumElems(sizeof...(Arg)) {}
 
    std::tuple<Arg...> mems;
    int NumElems;
};
 
int main() {
   struct A {};
   struct B {};
   struct C {};
 
   Base<A,B,C> obj;
}
объекты не создадутся или что?
1
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 02:31  [ТС] 5
gray_fox, а они разве добавятся в кортеж? К тому же, структуры A,B и C все-таки не в main будут определяться.
0
Jupiter
29.07.2013, 02:37
  #6

Не по теме:

Цитата Сообщение от gray_fox Посмотреть сообщение
объекты не создадутся или что?
я огород нагородил..:D пора спать

0
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
29.07.2013, 02:40 7
Gorillych, ну члены mems будут сконструированны (value-initialized вроде), если про это; либо я не понял...

Добавлено через 1 минуту
Цитата Сообщение от Gorillych Посмотреть сообщение
К тому же, структуры A,B и C все-таки не в main будут определяться.
не суть...
0
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 19:01  [ТС] 8
Если кому интересно - ниже реализация гетерогенного контейнера, наподобие boost::any. Можно обходить элементы контейнера наподобие массивам, но в компайл-тайме:
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
namespace static_iterator
{
    template <int... Idx>
    struct index { };
 
    template <int N, int... Idx>
    struct sequence : sequence<N - 1, N - 1, Idx...> { };
 
    template <int... Idx>
    struct sequence<0, Idx...> : index<Idx...> { };
}
 
 
 
struct A {void prnt(){std::cout<<"A\n";} };    
struct B {void prnt(){std::cout<<"B\n";} };    
struct C {void prnt(){std::cout<<"C\n";} };
 
template<typename...Arg>
class HeterogenousContainer
{
public:
    HeterogenousContainer() : 
            number_elems(sizeof...(Arg)), 
            elements(std::make_tuple(Arg()...)){}
 
    std::tuple<Arg...> elements;
 
    template <int... Idx>
    void process(static_iterator::index<Idx...>)
    {
         auto aux = { (std::get<Idx>(elements).prnt(), 0) ... };
    }
 
    void process()
    {
        process(static_iterator::sequence<sizeof...(Arg)>());
    }
    
    unsigned int get_number_elements(){return number_elems;}
    
private:
    unsigned int number_elems;
};
int main()
{  
    HeterogenousContainer<A,B,C,A,A,B,C,B,B,C> obj;
    obj.process();
}
1
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
29.07.2013, 19:26 9
Gorillych, я до сих пор не понял, чем
C++
1
2
3
HeterogenousContainer() : 
            number_elems(sizeof...(Arg)), 
            elements(std::make_tuple(Arg()...)){}
отличается от
C++
1
2
HeterogenousContainer() : 
            number_elems(sizeof...(Arg)) {}
?
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
29.07.2013, 19:32 10
Цитата Сообщение от Gorillych Посмотреть сообщение
C++
1
2
3
HeterogenousContainer() : 
    number_elems(sizeof...(Arg)), 
    elements(std::make_tuple(Arg()...))
gray_fox, ничем

Gorillych, если уж делаешь список инициализации то инициализируй поля в том порядке, в котором они объявлены в классе т.е.
C++
1
2
3
HeterogenousContainer() : 
    elements(std::make_tuple(Arg()...)),
    number_elems(sizeof...(Arg))
хотя тут это особой роли не играет, но лучше всегда придерживаться этого
1
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 19:34  [ТС] 11
gray_fox, ну как же. Я чего хотел добиться: в параметрах шаблона HeterogeneousContainer мы указываем список объектов классов, которые мы бы хотели добавить в контейнер. Далее в списке инициализации мы в кортеж добавляем экземпляры объектов перечисленных классов. Если убрать elements(std::make_tuple(Arg()...)), то кортеж будет пустой. Это получается что-то вроде:
C++
1
std::vector<boost::any> obj;
только полностью в компайле и обход поэлементный тоже в компайле.

P.S. Попробуйте скомпилировать c elements(std::make_tuple(Arg()...)) и без
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.07.2013, 19:39 12
Gorillych, И? https://ideone.com/3bdwJx
Отличий никаких, просто потому, что в кортеже все аргументы будут созданы, используя дефолтный конструктор, ровно это же делает и ваша конструкция.
Это, не то что вы сказали, это
C++
1
std::vector<boost::variant<A, B, C>>
, any тут ни при чем.
1
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 19:42  [ТС] 13
ForEveR, хм....
У меня не компилится почему-то
З.Ы. Все нормально))) Не то делал. Получается, действительно не нужно. Это очень даже хорошо
0
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
29.07.2013, 19:44 14
Цитата Сообщение от Gorillych Посмотреть сообщение
то кортеж будет пустой
Да нет... если надо "пустой", то что-нибудь вроде
C++
1
std::tuple<boost::optional<Arg>...> mems;
тогда разница будет между
C++
1
mems()
и
C++
1
mems(Arg()...)
1
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 19:48  [ТС] 15
gray_fox, да, понял.

Добавлено через 3 минуты
gray_fox, а вот интересно: если у структур A B C будут конструкторы не по умолчанию, с параметрами, как тогда быть?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.07.2013, 19:49 16
Gorillych, Тогда, так как сделали вы +-.
0
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 19:50  [ТС] 17
ForEveR, т.е. здесь уже явно нужен будет make_tuple, да?
0
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
29.07.2013, 19:54 18
Gorillych, эмм, наверное так
C++
1
2
template<typename ...Other>
Base(Other && ...other) : mems(std::forward<Other>(other)...) {}
1
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.07.2013, 19:55 19
Gorillych, Можно и конструктор просто вызвать...
0
29.07.2013, 19:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.07.2013, 19:55
Помогаю со студенческими работами здесь

Шаблонная функция с переменным числом аргументов
Сабж. Каким образом можно запретить использование шаблонной функции, если тип одного из аргументов...

GCC и функции с переменным числом аргументов
Писал мини приложение в студии для работы с векторами, один из методов просто получает сколько...

Функция с переменным числом аргументов (через шаблоны)
Доброго времени суток! Встал вопрос с реализацией такой функции. template&lt;typename... Args&gt;...

Шаблон с переменным числом аргументов, и возвращаемое значение функции
Здравствуйте! Использую С++11. Хочу возвращать элементы кортежа пытаюсь так, auto...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru