специализация шаблона для произвольного енума
От: RikkiTikkiTavi Россия  
Дата: 09.09.13 09:18
Оценка:
Здравствуйте!

В шаблонной магии не силен, нужна помощь.

Есть такая задачка (формулировка здесь надуманна): сохраняем опции, скажем, в поток. Опции могут быть как стандартных типов, так и кастомных.
struct Options {
    option<int> i;
    option<std::string> s;
    option<My_type> m;
    option<enum E> e;
};

Опции представлены в виде обертки
template <class T>
struct option {
    ...
    T m_val;

    void SaveToFile( ostream& s)
    {
        Save( m_val, s );
    }
};

Нужна сериализация в поток для каждого типа. Чтобы "магически" разруливалось компилятором, я решил использовать перегрузку.
Для стандартных типов достаточно простой шаблонной реализации
template <class T>
void Save( const T& val, ostream& s)
{
    s << val;
}

Для специфического типа я пишу специализацию, все ништяк работает:
void Save( const My_type& val, ostream& s)
{
    s << ...;
}

А вот енумы я хочу сериализовывать в лонги, и при этом хочется написать одну функцию. Что-то типа:
void Save( const MyEnum& val, ostream& s)
{
    s << long(val);
}

Вопрос в том как заставить компилятор использовать отдельную специализацию для енумов?
Я пытался использовать enable_if + is_enum, но у меня не получилось (enable_if методом дополнительного параметра — из-за этого не компилируются специализации).

Подскажите плз
Re: специализация шаблона для произвольного енума
От: jazzer Россия Skype: enerjazzer
Дата: 09.09.13 09:52
Оценка:
Здравствуйте, RikkiTikkiTavi, Вы писали:

RTT>Для стандартных типов достаточно простой шаблонной реализации

RTT>
RTT>template <class T>
    typename disable_if<is_enum<T>>::type
RTT>Save( const T& val, ostream& s)
RTT>{
RTT>    s << val;
RTT>}
RTT>


RTT>А вот енумы я хочу сериализовывать в лонги, и при этом хочется написать одну функцию. Что-то типа:

RTT>
    template <class T>
    typename enable_if<is_enum<T>>::type
RTT>Save( const T& val, ostream& s)
RTT>{
RTT>    s << long(val);
RTT>}
RTT>
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: специализация шаблона для произвольного енума
От: Went  
Дата: 09.09.13 09:56
Оценка:
Здравствуйте, RikkiTikkiTavi, Вы писали:
RTT>Я пытался использовать enable_if + is_enum, но у меня не получилось (enable_if методом дополнительного параметра — из-за этого не компилируются специализации).
Оберни возвращаемое значение:
template<class EnumT>
typename boost::enable_if<boost::is_enum<EnumT>, BStream&>::type operator << (BStream& bstr, EnumT rhv)
{
  bstr << static_cast<Int>(rhv);
  return bstr;
}

template<class EnumT>
typename boost::enable_if<boost::is_enum<EnumT>, BStream&>::type operator >> (BStream& bstr, EnumT& rhv)
{
  Int temp;
  bstr >> temp;
  rhv = static_cast<EnumT>(temp);
  return bstr;
}
Re[2]: специализация шаблона для произвольного енума
От: jazzer Россия Skype: enerjazzer
Дата: 09.09.13 10:01
Оценка: +1
Здравствуйте, Went, Вы писали:

W>Оберни возвращаемое значение:

W>
W>template<class EnumT>
W>typename boost::enable_if<boost::is_enum<EnumT>, BStream&>::type operator << (BStream& bstr, EnumT rhv)
W>


Этого недостаточно — для перечислений оно будет конфликтовать с общим шаблоном (который тоже подходит), так что его тоже надо защитить явно через disable_if.

P.S. Ессно, если ввести еще пару условий, то все превратится в кощмар, как справиться с ним, читать здесь: http://rsdn.ru/?forum/cpp/3722136
Автор: jazzer
Дата: 02.03.10
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: специализация шаблона для произвольного енума
От: Кодт Россия  
Дата: 09.09.13 10:58
Оценка:
Здравствуйте, RikkiTikkiTavi, Вы писали:

RTT>А вот енумы я хочу сериализовывать в лонги, и при этом хочется написать одну функцию. Что-то типа:


Именно в лонги? Потому что если не придумывать специализацию под энум, а просто написать Save(my_enum_value, std::cout), то будет воплощён основной шаблон, внутри него std::cout<<my_enum_value, превратится в int или ближайший подходящий целый тип (unsigned, long, unsigned long, long long...) и нормально выведется.
Перекуём баги на фичи!
Re[3]: специализация шаблона для произвольного енума
От: Went  
Дата: 09.09.13 14:09
Оценка:
Здравствуйте, jazzer, Вы писали:
J>Этого недостаточно — для перечислений оно будет конфликтовать с общим шаблоном (который тоже подходит), так что его тоже надо защитить явно через disable_if.
Да, точно, забыл, у меня нет "общего шаблона".

J>P.S. Ессно, если ввести еще пару условий, то все превратится в кощмар, как справиться с ним, читать здесь: http://rsdn.ru/?forum/cpp/3722136
Автор: jazzer
Дата: 02.03.10

Ну, я такое решаю введением второго аргумента-стратегии, это позволяет спрятать "общий" шаблон вовнутрь и спокойно пользоваться перегрузкой и enable_if (общее поведение прячется под "..." или некий дамми-класс с шаблонным конструктором).
Re: специализация шаблона для произвольного енума
От: niXman Ниоткуда https://github.com/niXman
Дата: 11.09.13 07:22
Оценка:
Здравствуйте, RikkiTikkiTavi, Вы писали:

RTT>Нужна сериализация в поток для каждого типа. Чтобы "магически" разруливалось компилятором, я решил использовать перегрузку.

не нужно ничего "изобретать", используй готовое
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.