Форум программистов, компьютерный форум CyberForum.ru

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.89
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
#1

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

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

Добрый вечер.
Мне нужно инициализировать объект 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 наподобие массиву (в цикле, например)?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.07.2013, 00:38
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Инициализация std::tuple переменным числом аргументов (C++):

Шаблоны с переменным числом аргументов - C++
Написал шаблон функции с переменным числом аргументов которая считает сумму своих аргументов. Практики по этому вопросу не имею, поэтому...

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

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

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

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

Шаблон с переменным числом аргументов, и возвращаемое значение функции - C++
Здравствуйте! Использую С++11. Хочу возвращать элементы кортежа пытаюсь так, auto Deserialize(unsigned long long i) -&gt;...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
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;
}
Gorillych
14 / 14 / 1
Регистрация: 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;
 
};
gray_fox
What a waste!
1507 / 1210 / 68
Регистрация: 21.04.2012
Сообщений: 2,545
Завершенные тесты: 3
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;
}
объекты не создадутся или что?
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 02:31  [ТС] #5
gray_fox, а они разве добавятся в кортеж? К тому же, структуры A,B и C все-таки не в main будут определяться.
Jupiter
29.07.2013, 02:37
  #6

Не по теме:

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

gray_fox
What a waste!
1507 / 1210 / 68
Регистрация: 21.04.2012
Сообщений: 2,545
Завершенные тесты: 3
29.07.2013, 02:40 #7
Gorillych, ну члены mems будут сконструированны (value-initialized вроде), если про это; либо я не понял...

Добавлено через 1 минуту
Цитата Сообщение от Gorillych Посмотреть сообщение
К тому же, структуры A,B и C все-таки не в main будут определяться.
не суть...
Gorillych
14 / 14 / 1
Регистрация: 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();
}
gray_fox
What a waste!
1507 / 1210 / 68
Регистрация: 21.04.2012
Сообщений: 2,545
Завершенные тесты: 3
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)) {}
?
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
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))
хотя тут это особой роли не играет, но лучше всегда придерживаться этого
Gorillych
14 / 14 / 1
Регистрация: 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()...)) и без
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
29.07.2013, 19:39 #12
Gorillych, И? https://ideone.com/3bdwJx
Отличий никаких, просто потому, что в кортеже все аргументы будут созданы, используя дефолтный конструктор, ровно это же делает и ваша конструкция.
Это, не то что вы сказали, это
C++
1
std::vector<boost::variant<A, B, C>>
, any тут ни при чем.
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 19:42  [ТС] #13
ForEveR, хм....
У меня не компилится почему-то
З.Ы. Все нормально))) Не то делал. Получается, действительно не нужно. Это очень даже хорошо
gray_fox
What a waste!
1507 / 1210 / 68
Регистрация: 21.04.2012
Сообщений: 2,545
Завершенные тесты: 3
29.07.2013, 19:44 #14
Цитата Сообщение от Gorillych Посмотреть сообщение
то кортеж будет пустой
Да нет... если надо "пустой", то что-нибудь вроде
C++
1
std::tuple<boost::optional<Arg>...> mems;
тогда разница будет между
C++
1
mems()
и
C++
1
mems(Arg()...)
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
29.07.2013, 19:48  [ТС] #15
gray_fox, да, понял.

Добавлено через 3 минуты
gray_fox, а вот интересно: если у структур A B C будут конструкторы не по умолчанию, с параметрами, как тогда быть?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.07.2013, 19:48
Привет! Вот еще темы с ответами:

Как изменить значение переменной, переданной в списке с переменным числом аргументов - C++
Помогите!!! Начал изучать С++ Возникла такая проблема. Когда мне нужно получить доступ к переменному числу аргументов я делаю что-то...

Как пройтись по всем типам std::tuple - C++
Здравствуйте! Как пройтись по всем типам std::tuple, не создавая экземпляр подобного объекта? Добавлено через 54 минуты Вопрос...

Как сделать один универсальный класс-контейнер а-ля std::tuple из двух различных классов? - C++
Добрый день. Есть работающий код: #include &lt;iostream&gt; #include &lt;map&gt; enum Index { First, Second, ...

Шаблон функции с переменным количеством аргументов - C++
Добрый вечер, мне необходимо при помощи шаблона функции реализовать поиск минимального числа(тип данных не известен, количество чисел...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
29.07.2013, 19:48
Ответ Создать тему
Опции темы

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