метаданные
От: #zss#  
Дата: 17.10.09 11:45
Оценка:
необходимо хранить данные различных типов в некой структуре.
Требование к объекту
1. Хранение различных типов
2. возможность проверки наличия данных
3. возможность добавления данных различного типа

Сначала была идея реализовать данные в виде тегов и набора масок для проверки наличия, но есть надежда, что можно проще.
Например std::map c типом variant

Что проще для реализации ? Или может что есть готовое для этих целей ?
Re: метаданные
От: _nn_ www.nemerleweb.com
Дата: 17.10.09 12:33
Оценка:
Здравствуйте, #zss#, Вы писали:

Z>необходимо хранить данные различных типов в некой структуре.

Z>Требование к объекту
Z>1. Хранение различных типов
Z>2. возможность проверки наличия данных
Z>3. возможность добавления данных различного типа

Z>Сначала была идея реализовать данные в виде тегов и набора масок для проверки наличия, но есть надежда, что можно проще.

Z>Например std::map c типом variant

Z>Что проще для реализации ? Или может что есть готовое для этих целей ?


Если типы известны на этапе компиляции, то можно vector<boost::variant> или может vector<boost::option<boost::variant>>.
Если типы неизвестны, то тогда либо нужен интерфейс и тогда ptr_vector<BaseClass> либо vector<boost::any> если вообще ничего не известно.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: метаданные
От: #zss#  
Дата: 17.10.09 12:41
Оценка:
__>Если типы известны на этапе компиляции, то можно vector<boost::variant> или может vector<boost::option<boost::variant>>.
__>Если типы неизвестны, то тогда либо нужен интерфейс и тогда ptr_vector<BaseClass> либо vector<boost::any> если вообще ничего не известно.

Ну тут немного проще. Объясню.

Была некая структура

struct S
{
   int a;
   int b;
   int c;
}


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

Но тут понадобилось обработчикам скормить новую

struct S2
{
   int a;
   int c;
   int d;
}


Логично тогда отдавать им не данные, а некий метаобъект, который может проверять и отдавать необходимые данные.
Только одно требование — обработчики помимо доступа к данным должны знать что за данные пришли S или S2
Re[2]: метаданные
От: #zss#  
Дата: 17.10.09 12:41
Оценка:
__>Если типы известны на этапе компиляции, то можно vector<boost::variant> или может vector<boost::option<boost::variant>>.
__>Если типы неизвестны, то тогда либо нужен интерфейс и тогда ptr_vector<BaseClass> либо vector<boost::any> если вообще ничего не известно.

а для чего boost::option и boost::any ?
Re[3]: метаданные
От: _nn_ www.nemerleweb.com
Дата: 17.10.09 14:17
Оценка:
Здравствуйте, #zss#, Вы писали:

Значит известны типы на этапе компиляции.
Тогда можно использовать Boost.Fusion: http://www.boost.org/doc/libs/1_40_0/libs/fusion/doc/html/index.html

С помощью BOOST_FUSION_ADAPT_STRUCT можно составить последовательность Boost.Fusion и тогда работать с двумя структурами как с последовательностями данных.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: метаданные
От: Sni4ok  
Дата: 17.10.09 16:47
Оценка:
Здравствуйте, #zss#, Вы писали:

boost::any уже подсказали, а ещё как вариант- boost::variant, если множество возможных типов известно.
Re[4]: метаданные
От: #zss#  
Дата: 17.10.09 17:58
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Здравствуйте, #zss#, Вы писали:


__>Значит известны типы на этапе компиляции.

__>Тогда можно использовать Boost.Fusion: http://www.boost.org/doc/libs/1_40_0/libs/fusion/doc/html/index.html

__>С помощью BOOST_FUSION_ADAPT_STRUCT можно составить последовательность Boost.Fusion и тогда работать с двумя структурами как с последовательностями данных.

спасибо — почитаю
Re[2]: метаданные
От: #zss#  
Дата: 17.10.09 18:00
Оценка:
Здравствуйте, Sni4ok, Вы писали:

S>Здравствуйте, #zss#, Вы писали:


S>boost::any уже подсказали, а ещё как вариант- boost::variant, если множество возможных типов известно.


Тут нужна именно проверка по типу.
То есть из данных нужно спросить есть ли данное поле. Типы конечно известны.

А как у вектора спросить ? тем более, что могут быть различные данные одного типа. То есть тут нужна привязка данных к типу (имеется ввиду к полю).
Re[2]: метаданные
От: #zss#  
Дата: 21.10.09 10:05
Оценка:
Здравствуйте, Sni4ok, Вы писали:
S>boost::any уже подсказали, а ещё как вариант- boost::variant, если множество возможных типов известно.

Остановился на boost::variant. Но вот странное поведение.

Так работает.

#include "stdafx.h"
#include <map>
#include <string>
#include <boost/variant.hpp>

typedef unsigned char byte;
typedef unsigned int uint;
typedef unsigned short ushort;

class Params {
private :
    enum PARAMS { PP_STRING, PP_UINT, PP_BYTE };
    typedef boost::variant </*bool,*/ byte, uint, std::string> vatiant_t;
    typedef std::map<PARAMS, vatiant_t> prism_map_t;

    mutable prism_map_t m_map;
    template <class T> T get(PARAMS index) const { return boost::get<T>(m_map[index]); }

public :
    const std::string& getString (void) const { return get<const std::string&>(PP_STRING); }
    uint getUint    (void) const { return get<uint>(PP_UINT);    }
    byte getByte    (void) const { return get<byte>(PP_BYTE);    }

    Params& setUint        (uint value)    { m_map[PP_UINT] = value;    return *this; }
    Params& setByte        (byte value)    { m_map[PP_BYTE] = value;    return *this; }
    Params& setString    (const std::string& value) { m_map[PP_STRING] = value; return *this; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Params pparams;
    pparams.setString    ("xxx");
    pparams.setUint        (123);

    uint value1 = pparams.getUint();
    byte value2 = pparams.getByte(); 

    return 0;
}


Но вот если раскомментировать тип bool, то слетает на доступе к байту. Если же перенести описание bool

typedef boost::variant <byte, uint, std::string, bool> vatiant_t;


то опять работает. В чем причина ?
Re[3]: метаданные
От: Юрий Жмеренецкий ICQ 380412032
Дата: 21.10.09 14:18
Оценка:
Здравствуйте, #zss#, Вы писали:

Z>
Z>#include "stdafx.h"
Z>#include <map>
Z>#include <string>
Z>#include <boost/variant.hpp>

Z>typedef unsigned char byte;
Z>typedef unsigned int uint;
Z>typedef unsigned short ushort;

Z>class Params {
Z>private :
Z>    enum PARAMS { PP_STRING, PP_UINT, PP_BYTE };
Z>    typedef boost::variant </*bool,*/ byte, uint, std::string> vatiant_t;
Z>    typedef std::map<PARAMS, vatiant_t> prism_map_t;

Z>    mutable prism_map_t m_map;
Z>    template <class T> T get(PARAMS index) const { return boost::get<T>(m_map[index]); }

Z>public :
Z>    const std::string& getString (void) const { return get<const std::string&>(PP_STRING); }
Z>    uint getUint    (void) const { return get<uint>(PP_UINT);    }
Z>    byte getByte    (void) const { return get<byte>(PP_BYTE);    }

Z>    Params& setUint        (uint value)    { m_map[PP_UINT] = value;    return *this; }
Z>    Params& setByte        (byte value)    { m_map[PP_BYTE] = value;    return *this; }
Z>    Params& setString    (const std::string& value) { m_map[PP_STRING] = value; return *this; }
Z>};

Z>int _tmain(int argc, _TCHAR* argv[])
Z>{
Z>    Params pparams;
Z>    pparams.setString    ("xxx");
Z>    pparams.setUint        (123);

Z>    uint value1 = pparams.getUint();
Z>    byte value2 = pparams.getByte(); 

Z>    return 0;
Z>}
Z>


Z>Но вот если раскомментировать тип bool, то слетает на доступе к байту. Если же перенести описание bool


Z>
Z>typedef boost::variant <byte, uint, std::string, bool> vatiant_t;
Z>


Z>то опять работает. В чем причина ?


boost::variant никогда не бывает "пустым" (метод 'boost::variant<...>::empty()' всегда возвращает false) и при отсутствии явной инициализации в качестве хранимого типа используется первый из списка, т.е.:
boost::variant<T1, T2, ...> v; // ok (если T1 является DefaultConstructible)

T1 v1 = boost::get<T1>(v); // ok, v хранит объект типа T1 
T2 v2 = boost::get<T2>(v); // throw, типы хранимого и запрашиваемого не совпадают


Что происходит у тебя:

typedef boost::variant <bool, byte, uint, std::string> vatiant_t;
//...

Params pparams;
pparams.setString    ("xxx"); // 1
pparams.setUint        (123);   // 2


uint value1 = pparams.getUint(); // 3
byte value2 = pparams.getByte(); // 4


В строке с номером один выполняется 'm_map[PP_STRING] = value'. Вызов 'operator []' сначала приводит к вставке в m_map элемента с ключом 'PP_STRING' и значением 'vatiant_t()' и только потом вызывается оператор присваивания, который корректно обрабатывает эту ситуацию (присвоение объекта другого типа). В строке 2 выполняются аналогичные действия, и после ее выполнения количество объектов в m_map равено двум (с ключами PP_STRING и PP_UINT).

Выполнение строки 3 приводит к токому вызову: 'return boost::get<T>(m_map[index]);', где в качестве index используется PP_UINT. Объект с таким ключом будет успешно найден и возвращен. Но аналогичный вызов в строке 4 будет использовать в качестве ключа значение PP_BYTE. Объект с таким ключом в m_map отсутствует и учитывая что семантика 'operator []' для std::map выражается как 'вернуть элемент если он найден или, в противном случае, вставить элемент со значением по умолчанию и вернуть его' и m_map объявлен со спецификатором 'mutable', то сначала произойдет вставка элемента с ключом PP_BYTE и значением 'boost::variant()' (а это фактически bool). Далее функция 'boost::get<T>' обнаружет что типы хранимого объекта и запрашиваемого не совпадают и сгенерирует исключение, результат которого ты наблюдаешь.

Если использовать такой тип — 'boost::variant <byte, uint, std::string, bool>', то сценарий работы не изменится за исключеним того факта что при инициализации по умолчанию объект boost::variant будет хранить объект типа byte (первый в списке), и этот тип совпадает с запрашиваемым в 'boost::get'.
Re[4]: метаданные
От: #zss#  
Дата: 21.10.09 18:24
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>boost::variant никогда не бывает "пустым" (метод 'boost::variant<...>::empty()' всегда возвращает false) и при отсутствии явной инициализации в качестве хранимого типа используется первый из списка, т.е.:

ЮЖ>
boost::variant<T1, T2, ...> v; // ok (если T1 является DefaultConstructible)

ЮЖ>T1 v1 = boost::get<T1>(v); // ok, v хранит объект типа T1 
ЮЖ>T2 v2 = boost::get<T2>(v); // throw, типы хранимого и запрашиваемого не совпадают


ЮЖ>Что происходит у тебя:


ЮЖ>
ЮЖ>typedef boost::variant <bool, byte, uint, std::string> vatiant_t;
ЮЖ>//...

ЮЖ>Params pparams;
ЮЖ>pparams.setString    ("xxx"); // 1
ЮЖ>pparams.setUint        (123);   // 2


ЮЖ>uint value1 = pparams.getUint(); // 3
ЮЖ>byte value2 = pparams.getByte(); // 4
ЮЖ>


ЮЖ>В строке с номером один выполняется 'm_map[PP_STRING] = value'. Вызов 'operator []' сначала приводит к вставке в m_map элемента с ключом 'PP_STRING' и значением 'vatiant_t()' и только потом вызывается оператор присваивания, который корректно обрабатывает эту ситуацию (присвоение объекта другого типа). В строке 2 выполняются аналогичные действия, и после ее выполнения количество объектов в m_map равено двум (с ключами PP_STRING и PP_UINT).


ЮЖ>Выполнение строки 3 приводит к токому вызову: 'return boost::get<T>(m_map[index]);', где в качестве index используется PP_UINT. Объект с таким ключом будет успешно найден и возвращен. Но аналогичный вызов в строке 4 будет использовать в качестве ключа значение PP_BYTE. Объект с таким ключом в m_map отсутствует и учитывая что семантика 'operator []' для std::map выражается как 'вернуть элемент если он найден или, в противном случае, вставить элемент со значением по умолчанию и вернуть его' и m_map объявлен со спецификатором 'mutable', то сначала произойдет вставка элемента с ключом PP_BYTE и значением 'boost::variant()' (а это фактически bool). Далее функция 'boost::get<T>' обнаружет что типы хранимого объекта и запрашиваемого не совпадают и сгенерирует исключение, результат которого ты наблюдаешь.


ЮЖ>Если использовать такой тип — 'boost::variant <byte, uint, std::string, bool>', то сценарий работы не изменится за исключеним того факта что при инициализации по умолчанию объект boost::variant будет хранить объект типа byte (первый в списке), и этот тип совпадает с запрашиваемым в 'boost::get'.


Понятно. Но у меня нет возможности инициализировать map изначально правильными значениями. Тоесть исключение правильно возникает, т.к. данное свойство не инициализировано. Поэтому и была идея использовать map, чтоб при отсутствии данных возвращалось значение по-умолчанию (а точнее T()).

Чтоб не ловить исключения что можно сделать ? может boost::any ?
То есть идея в том, что данные могут быть, а могут и не быть в зависимости от инициализации.

Для структур это типа

struct S
{
    type1 t1;
    type2 t2;
    ...
    typeN tn;

    S () : t1(), t2(),...,tn() {}
}

S s;
s t1 = ...;
type2 t2 = s.t2; // здесь t2 == type2()
Re[5]: метаданные
От: Юрий Жмеренецкий ICQ 380412032
Дата: 21.10.09 21:22
Оценка:
Здравствуйте, #zss#, Вы писали:

Z>Понятно. Но у меня нет возможности инициализировать map изначально правильными значениями. Тоесть исключение правильно возникает, т.к. данное свойство не инициализировано. Поэтому и была идея использовать map, чтоб при отсутствии данных возвращалось значение по-умолчанию (а точнее T()).


Z>Чтоб не ловить исключения что можно сделать ?


Можно отказаться от использования 'operator[]' и при отсутствии элемента вставлять variant c необходимым типом (в Params::get он известен). Только std::map там не к месту, имхо.

Z>может boost::any ?

Z>То есть идея в том, что данные могут быть, а могут и не быть в зависимости от инициализации.

Непонятно чего хочется — то "могут быть, а могут и не быть", то аналога структуры. Вот такой способ:

#include <boost/tuple/tuple.hpp>
#include <cassert>
#include <string>

struct S : boost::tuples::tuple<int, bool, std::string>
{
  enum property { prop1, prop2, prop3 };
};

int main()
{
  S s; 

  s.get<S::prop1>() = 1;
  s.get<S::prop2>() = false;
  s.get<S::prop3>() = "abc";
        
  assert(s.get<S::prop1>() == 1);
  assert(s.get<S::prop2>() == false);
  assert(s.get<S::prop3>() == "abc");
}

чем не устраивает?
Re[6]: метаданные
От: #zss#  
Дата: 22.10.09 04:30
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>Можно отказаться от использования 'operator[]' и при отсутствии элемента вставлять variant c необходимым типом (в Params::get он известен).

принято

ЮЖ>Только std::map там не к месту, имхо.

почему ? изначально был смысл проверять наличие данных, но от исключений пришлось отказаться...
Re[7]: метаданные
От: Юрий Жмеренецкий ICQ 380412032
Дата: 22.10.09 06:26
Оценка:
Здравствуйте, #zss#, Вы писали:

ЮЖ>>Только std::map там не к месту, имхо.

Z>почему ?

Набор типов (enum PARAMS) фиксирован и не может изменяться в runtime, + типы не могут повторяться. Хотя я так и не понял, для каких сценариев использования все это необходимо. Например:

Z>Только одно требование — обработчики помимо доступа к данным должны знать что за данные пришли S или S2


struct client {
 void process(S&);
 void process(S2&);
};


Такое решение формально подходит. Или сигнатура "обработчика" единственная? Т.е. приблизительно такая:

void process(const метаданные&, данные&)


Насколько здесь важно 'обработчики... должны знать что за данные пришли S или S2' ? И в чем выражается это знание? Изменения S/S2/.. должны приводить к перекомпиляции клиентов или нет? С помощью чего должна осуществляться идентификация свойств одинаковых типов? Без ответов можно только гадать:

void process(AbstractS& ps) // интерфейс не знает о конкретных типах, только о базе.
{
  if(S* s = dynamic_cast<S*>(&ps)) // реализация знает про S
  {
    //...
  }
  else if (S2* s = dynamic_cast<S2*>(&ps)) // и про S2
  {
    //...
  }
}


struct process : boost::static_visitor<> // интерфейс знает о обрабатываемых типах 
{
  void operator()(S& i) const // реализация знает про S
  { /**/ }

  void operator()(S1& str) const // и про S2
  { /**/ }
};
//...
boost::variant<S, S1> v = ...
boost::apply_visitor(process(), v );


struct property_set
{
  virtual int read_int(const char* name) const = 0;
  //...
};

struct S : property_set
{
  int read_int(const char* name) const
  {/**/}
};

//...

void process(property_set& ps) // интерфейсу вообще ничего неизвестно
{
  if(const int* v = ps.read_int("SomeValue")) // реализации ничего не известно (про S)
  {
    //...
  }
}


Или все совсем не так? Тогда желаемый сценарий использования в студию...
Re[8]: метаданные
От: #zss#  
Дата: 22.10.09 07:40
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Насколько здесь важно 'обработчики... должны знать что за данные пришли S или S2' ? И в чем выражается это знание? Изменения S/S2/.. должны приводить к перекомпиляции клиентов или нет?

что-то я уже запутался. Смысл следующий. Разные устройства отдают мне различные данные. Они могут пересекаться.
Но на выходе мне нужно выдать свои наборы данных. Помимо этого обработчики перед выходом должны проанализировать эти данные. Вот и возникла идея между входным интерфейсом и выходным хранить некие метаданные для их обработки. Тогда мои обработчики не зависят от входного и выходного интерфейса.

ЮЖ>С помощью чего должна осуществляться идентификация свойств одинаковых типов?

ну вот именно для этого я и взял map

P.S. Ты говорил, что можно избавиться от исключения типа

template <class T> get (PARAMS index) const
{
    map::iterator it = m_map.find(index);
    if (it == m_map.end()) m_map[index] = T(); 
    return boost::get<T>(m_map[index]);
}


но проблема в том, что у меня есть POD-типы у которых нет конструкторов. и тогда это

const timeval& time (void) const { return get<const timeval&>(...));


приводит к error C2101.
Re[8]: метаданные
От: #zss#  
Дата: 22.10.09 07:51
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

не дописал...
то есть получается, что я хочу ссылочный тип, который нельзя создать.
Re[9]: метаданные
От: Юрий Жмеренецкий ICQ 380412032
Дата: 22.10.09 10:18
Оценка:
Здравствуйте, #zss#, Вы писали:

Z>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Насколько здесь важно 'обработчики... должны знать что за данные пришли S или S2' ? И в чем выражается это знание? Изменения S/S2/.. должны приводить к перекомпиляции клиентов или нет?

Z>что-то я уже запутался. Смысл следующий. Разные устройства отдают мне различные данные. Они могут пересекаться.
Z>Но на выходе мне нужно выдать свои наборы данных. Помимо этого обработчики перед выходом должны проанализировать эти данные.

Количество обработчиков зависит от количества устройств?

Z>Вот и возникла идея между входным интерфейсом и выходным хранить некие метаданные для их обработки.


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

Z>Тогда мои обработчики не зависят от входного и выходного интерфейса.


А вот, кажется и проблемы. Т.е. сейчас обработчики привязаны к форматам данных, в которых отдают информацию устройства, но это приводит к зависимостям, которые нужно устранить?

ЮЖ>>С помощью чего должна осуществляться идентификация свойств одинаковых типов?

Z>ну вот именно для этого я и взял map

Как это предпологается использовать в случае необходимости иметь, например два таких свойства — дата начала и дата окончания (чего-либо)?

Z>P.S. Ты говорил, что можно избавиться от исключения типа


Z>
Z>template <class T> get (PARAMS index) const
Z>{
Z>    map::iterator it = m_map.find(index);
Z>    if (it == m_map.end()) m_map[index] = T(); 
Z>    return boost::get<T>(m_map[index]);
Z>}
Z>


Это будет работать, но я говорил об избавлении от 'operator[]'.

Z>но проблема в том, что у меня есть POD-типы у которых нет конструкторов. и тогда это


Z>
Z>const timeval& time (void) const { return get<const timeval&>(...));
Z>


Z>приводит к error C2101.


.. get<const timeval&>
//                  ^--- нужно убрать, boost::get умеет возвращать ссылки
Re[10]: метаданные
От: #zss#  
Дата: 22.10.09 10:33
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Количество обработчиков зависит от количества устройств?

Нет. Обработчики просто стоят в очереди. А данные, которые приходят от устройств могут содержать необходимое или нет.
Если нет — ну и хрен с ним. А вот если содержат, то это нужно проанализировать. Тоесть устройства могут быть различных типов.

ЮЖ>Эта идея ведь не спроста возникла... Она должна решать какие-то проблемы.

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

ЮЖ>А вот, кажется и проблемы. Т.е. сейчас обработчики привязаны к форматам данных, в которых отдают информацию устройства, но это приводит к зависимостям, которые нужно устранить?

Именно

Z>>P.S. Ты говорил, что можно избавиться от исключения типа


ЮЖ>Это будет работать, но я говорил об избавлении от 'operator[]'.

Как ? я тогда не разделю данные одного типа

ЮЖ>
.. get<const timeval&>
ЮЖ>//                  ^--- нужно убрать, boost::get умеет возвращать ссылки


Но ведь тогда get вернет по-значению и time получит ссылку на локальный объект.
Или я что-то не понял ?
Re[11]: метаданные
От: Юрий Жмеренецкий ICQ 380412032
Дата: 22.10.09 11:59
Оценка:
Здравствуйте, #zss#, Вы писали:

Z>>> Ты говорил, что можно избавиться от исключения типа


ЮЖ>>Это будет работать, но я говорил об избавлении от 'operator[]'.

Z>Как ?

map::find/map::insert или map::lower_bound + map::insert(hint,...). Но это не принципиально. Но раз уж ты выбрал std::map, то для хранения лучше будет обернуть variant_t в boost::optional<variant_t> — так сразу решается проблема с отсутствием свойства, и 'operator[]' будет работать без сюрпризов.

ЮЖ>>
.. get<const timeval&>
ЮЖ>>//                  ^--- нужно убрать, boost::get умеет возвращать ссылки


Z>Но ведь тогда get вернет по-значению


Если в качестве параметра этой функции передается ссылка (на объект типа variant), то и возвращает она ссылку на хранимое значение (опционально константную), а не значение. Схематично — так:
template<class T, class V>
/*const*/ T& boost::get(/*const*/ V& v)

При инстанцировании типом 'const timeval&' проиходит формирование ссылки на ссылку (для типа результата), что является ошибкой.
Re[12]: метаданные
От: #zss#  
Дата: 22.10.09 12:24
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>map::find/map::insert или map::lower_bound + map::insert(hint,...). Но это не принципиально. Но раз уж ты выбрал std::map, то для хранения лучше будет обернуть variant_t в boost::optional<variant_t> — так сразу решается проблема с отсутствием свойства, и 'operator[]' будет работать без сюрпризов.
c boost::optional пока не разбирался. Для чего это чудо вообще ?

ЮЖ>Если в качестве параметра этой функции передается ссылка (на объект типа variant), то и возвращает она ссылку на хранимое значение (опционально константную), а не значение. Схематично — так:

ЮЖ>
ЮЖ>template<class T, class V>
ЮЖ>/*const*/ T& boost::get(/*const*/ V& v)
ЮЖ>

ЮЖ>При инстанцировании типом 'const timeval&' проиходит формирование ссылки на ссылку (для типа результата), что является ошибкой.

Ну примерно это и я попытался реализовать. Если ссылочный тип параметр, то и вернуть ссылку. Но у меня идет аргументом индекс, а не boost::variant.

Как тогда победить ? Иначе мне придется код для get (c проверкой наличия данных) вставлять в каждый метод
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.