Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Контейнер с несколькими типами данных 
:(
    Опции темы
neosapient
Дата 11.11.2013, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 672
Регистрация: 16.8.2006

Репутация: нет
Всего: 4



Здравствуйте.

Хочу сложить в контейнер ссылки на несколько типов данных. Но компилятор ругается на конструкцию std::vector<auto&>.

Как я понял, кортежи (std::tuple) требуют в момент компиляции указать размер списка  и не могут быть расширены динамически в процессе работы программы. Так что нужно решение без кортежей.

Для примера сделал некий шаблон и несколько типов на его основе:
Код

#pragma once
#include <string>

template <typename Type, char* Name>
struct my_shell{
    Type value;
    char *name;

    my_shell()
        : value()
        , name(Name)
    { }

    ~my_shell()
    { }
};

char sz_int[]   ="it is int";
char sz_double[]="it is double";
char sz_string[]="it is string";

struct my_int:    public my_shell<int, sz_int> {};
struct my_double: public my_shell<double, sz_double> {};
struct my_string: public my_shell<std::string, sz_string> {};


Хочу собрать ссылки на объекты в один vector и распечатать его.
Код

#include "stdafx.h"
#include "my_shell.hpp"
#include <vector>
#include <iostream>


int _tmain(int argc, _TCHAR* argv[])
{
    my_int    i1;
    my_double d1, d2;
    my_string s1, s2, s3;

    std::vector<auto&> test_vector; // <-- тут ругается
    test_vector.push_back(i1);
    test_vector.push_back(d1);
    test_vector.push_back(d2);
    test_vector.push_back(s1);
    test_vector.push_back(s2);
    test_vector.push_back(s3);

    for(auto a : test_vector)
        std::cout << a.name << std::endl;
    return 0;
}


Компилятор ругается, мол нельзя использовать тип auto (даже в виде ссылки) при инициализации vector'a.
1>c:\consoleapplication1\consoleapplication1.cpp(16): error C3539: 'auto &': a template-argument cannot be a type that contains 'auto'

Как быть, чтобы реализовать хотелку?

P.S.
Сборка идет в Visual Studio 2012 SP3 с ключем "Microsoft Visual C++ Compiler Nov 2012 CTP (v120_CTP_Nov2012)"

Это сообщение отредактировал(а) neosapient - 11.11.2013, 20:28
PM MAIL   Вверх
akizelokro
Дата 11.11.2013, 23:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Что такое "расширены динамически"?
Либо делай в tuple 6 указателей, или меньше. Либо делай базовый класс с производными для твоих трёх и вектор для этого базового класса


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
EgoBrain
Дата 12.11.2013, 04:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 23.3.2008
Где: Комната

Репутация: нет
Всего: 2



neosapient, вектор это контейнер для одного типа данных, может использовать полиморфизм и хранить нетипизированный указатель, либо указатель на базвый класс как посоветовал akizelokro...
В C++ есть что-то наподобии ArrayList в C#? Но "упаковки"/"распаковки" нет значит и такой коллекции тоже нет..
PM MAIL ICQ Skype   Вверх
vinter
Дата 12.11.2013, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



neosapient, ты не правильно понимаешь auto. Это не волшебный тип, который принимает всё, что угодно. Это просто указатель на то, что ты не хочешь печатать тип самостоятельно, чтобы компилятор сделал это за тебя. Это просто синтаксический сахар(если не брать в расчёт лямбды). Также, вектор может содержать только однородные данные, поэтому даже если бы auto могло бы вычислять типы на лету, ты бы всё равно не мог бы их хранить в векторе.

Решений твоей проблемы существует великое множество: полиморфизм, boost::any, boost::variant и еще куча разных техник, которые уже придуманы и которые еще нет. Я приведу одну, которую не надо долго писать:
Код

int main() {

    my_int    i1;
    my_double d1, d2;
    my_string s1, s2, s3;

    std::vector<std::function<char*()>> test_vector; // <-- тут ругается
    test_vector.push_back([&]{return i1.name;});
    test_vector.push_back([&]{return d1.name; });
    test_vector.push_back([&]{return d2.name; });
    test_vector.push_back([&]{return s1.name; });
    test_vector.push_back([&]{return s2.name; });
    test_vector.push_back([&]{return s3.name; });

    for(const auto& a : test_vector)
        std::cout << a() << std::endl;
    return 0;
}


Это сообщение отредактировал(а) vinter - 12.11.2013, 10:22


--------------------
Мой блог
PM MAIL WWW   Вверх
neosapient
Дата 12.11.2013, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 672
Регистрация: 16.8.2006

Репутация: нет
Всего: 4



Всем, спасибо, что принимаете участие в обсуждение.
Я уже склоняюсь к тому, чтобы сделать структуру-обертку надо несколькими типами данных + флаг актуального типа. 

Ситуация в следующем: есть набор критериев, определяющих некую норму и отклонения от нормы.

Была мысль воспользоваться кортежем (std::tuple), но, думаю, она провальна. И всё же поделюсь мыслями: 
Для примера, рассмотрим карточку пациента, который прошел комплексное обследование.
Ему заполнили следующие поля
- пульс
- давление верхнее
- давление нижнее
- единицы сахара в крови
- симулянт (тип bool)
- ещё куча параметров, записанных через типы bool, int, INT64, double, std::string

Я не врач, и я не могу грамотно составить списки правил. Врач будет долго разбираться в программировании.
По этому, я хочу с помощью шаблонов предоставить некий мета-код с которым разберется врач.

Сейчас реализацию проекта вижу примерно так. Есть структура типа pacient
Для каждого параметра написать функтор
struct {
    int operator() (pacient& p)
    { return p.davlenie; }
} puls;

struct {
    double operator() (pacient& p)
    { return p.davlenie; }
} sugar;

struct {
    bool operator() (pacient& p)
    { return p.simulant; }
} simulant;

Сделал обертки над std::less<T>, std::greater<T>, std::equal_to<T>
что то вроде
struct {
  std::less<bool> less_bool;
  std::less<int> less_int;
  std::less<INT64> less_int64;
  std::less<double> less_double;
  std::less<std::string> less_string;
  // операции сравнения
  bool operator () (int a, int b)
  { return less_bool(a,b);}
  // и так далее
  bool operator () (std::string a, std::string b)
  { return less_string(a,b);}
} less;



Meta-код должен получиться примерно такой:
auto rules = std::make_tuple (
  check(puls).is(less).than(60).print("у вас медленный пульс!")
  check(puls).is(greater).than(120).print("у вас быстрый пульс!")
  check(sugar).is(greater).than(10).print("у вас высокий сахар в крови!")
  check(simulant).is(equal).to(true).print("Срочно ректальная тонзиллэктомия!")
);

Создавемые check() объекты будут функторами.
В итоге получил объект rules, который хорошо бы сохранить на всё время жизни программы.
И организовать для проверки функцию check_rules(rules, obj_pacient)
где
check_rules(auto &rules, pacient& men)
{
  rules<1>(men);
  rules<2>(men);
  rules<3>(men);
  rules<4>(men);
...
  rules<N>(men);
}

От меня будет только требоваться добавлять строчки rules<N>(men); с увеличением счетчика

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

P.P.S.
Позволит ли компилятор записать?: 
struct A{
  auto value;
  A() : value(std::make_tuple (false, 1, "second")) {}
};
PM MAIL   Вверх
baldina
Дата 12.11.2013, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



погляди boost::variant
PM MAIL   Вверх
vinter
Дата 12.11.2013, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата

Позволит ли компилятор записать?:

Нет, auto переменная всегда должна быть чем-то инициализирована. Из инициализации, собственно, компилятор и возьмет тип который скрывается за auto.
Цитата

check_rules(auto &rules

так тоже нельзя.
Ты знаком с шаблонами? Судя по тому, куда ты пытаешься лепить auto, не очень smile

Это сообщение отредактировал(а) vinter - 12.11.2013, 12:57


--------------------
Мой блог
PM MAIL WWW   Вверх
neosapient
Дата 12.11.2013, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 672
Регистрация: 16.8.2006

Репутация: нет
Всего: 4



Цитата(vinter @ 12.11.2013,  12:57)
Ты знаком с шаблонами? Судя по тому, куда ты пытаешься лепить auto, не очень smile

Изучаю нововведения С++11.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0485 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.