Re: type converter
От: Alexander G Украина  
Дата: 26.09.18 12:32
Оценка: 6 (1) +2
Здравствуйте, SomeOne_TT, Вы писали:

SO_>да еще и ns_crap::Fruit как темплейт аргумент применить невозможно, т.к. это не тип и не значение.


Можно. Это переменная с внешним связыванием, можно параметризовать шаблон указателем на неё

template<ns_crap::Fruit*>
...
Русский военный корабль идёт ко дну!
Re: type converter
От: rg45 СССР  
Дата: 26.09.18 22:42
Оценка: 9 (1)
Здравствуйте, SomeOne_TT, Вы писали:

SO_>Есть три внешние иерархии типов, которые надо маппить друг в друга.

SO_>Первая иерархия построена на enum-like int
SO_>Третья — весьма странный (не понимаю, зачем?) способ
SO_>Задача — написать конвертер, который маппит значение из одной иерархии в другую.
SO_>Желаемый интерфейс — что-то вроде
SO_>Что ни придумаю — выходят какие-то уродцы, да еще и ns_crap::Fruit как темплейт аргумент применить невозможно, т.к. это не тип и не значение.
SO_>Какие есть варианты?

Я вот здесь набросал. Интерфейс сохранил в точности, как ты показал:

https://ideone.com/Fiv1OQ

Единственное изменение — статические ссылки на объеты Fruit пришлось заменить "живыми" объектами, иначе не удается сделать их параметрами шаблона.

Поддержка:

template <int V, typename T, const ns_crap::Fruit& O>
struct MapEntry
{
   static constexpr int value = V;
   using type = T;
   static constexpr const ns_crap::Fruit& object = O;
};
 
template <int> struct from_val;
template <typename> struct from_type;
template <const ns_crap::Fruit&> struct from_crap;
 
#define MAKE_MAP_ENTRY(value, type, object) \
   template <> struct from_val<value> : MapEntry<value, type, object> {}; \
   template <> struct from_type<type> : MapEntry<value, type, object> {}; \
   template <> struct from_crap<object> : MapEntry<value, type, object> {};


Использование:

MAKE_MAP_ENTRY(ns_val::APPLE, ns_types::Apple, ns_crap::Fruit::Apple)
MAKE_MAP_ENTRY(ns_val::PINEAPPLE, ns_types::Pineapple, ns_crap::Fruit::Pinapple)
MAKE_MAP_ENTRY(ns_val::PEAR, ns_types::Pear, ns_crap::Fruit::Pear)
 
// getting values
static_assert(from_val<ns_val::APPLE>::value == ns_val::APPLE, "");
static_assert(from_type<ns_types::Pineapple>::value == ns_val::PINEAPPLE, "");
static_assert(from_crap<ns_crap::Fruit::Pear>::value == ns_val::PEAR, "");
 
// getting types
static_assert(std::is_same<from_val<ns_val::APPLE>::type, ns_types::Apple>::value, "");
static_assert(std::is_same<from_type<ns_types::Pineapple>::type, ns_types::Pineapple>::value, "");
static_assert(std::is_same<from_crap<ns_crap::Fruit::Pear>::type, ns_types::Pear>::value, "");
 
// getting objects
static_assert(&from_val<ns_val::APPLE>::object == &ns_crap::Fruit::Apple, "");
static_assert(&from_type<ns_types::Pineapple>::object == &ns_crap::Fruit::Pinapple, "");
static_assert(&from_crap<ns_crap::Fruit::Pear>::object == &ns_crap::Fruit::Pear, "");
--
Отредактировано 26.09.2018 22:50 rg45 . Предыдущая версия .
Re: type converter
От: Voivoid Россия  
Дата: 26.09.18 13:24
Оценка: 6 (1)
Здравствуйте, SomeOne_TT, Вы писали:

SO_>Есть три внешние иерархии типов, которые надо маппить друг в друга.


https://coliru.stacked-crooked.com/a/3db9304bd1696a14

с помощью boost preprocessor можно сделать автоматическую генерацию from_val, from_type и from_crap mapper'ов ( см BOOST_PP_SEQ_FOR_EACH )
Re: type converter
От: Chorkov Россия  
Дата: 26.09.18 12:11
Оценка: 4 (1)
Здравствуйте, SomeOne_TT, Вы писали:


SO_>Третья — весьма странный (не понимаю, зачем?) способ


SO_>
SO_>namespace ns_crap
SO_>{
SO_>struct Fruit:Base_Fruit
SO_>{
SO_> public:
SO_>    static const Fruit& Apple;
SO_>    static const Fruit& Pineapple;
SO_>    static const Fruit& Pear;
SO_>}
SO_>}
SO_>


Обычно, этот способ применяют когда нужно сказать, что есть стандартные реализации некого интерфейса.
Например :
strcut OnError
{
    virtual void operator() ( const char* ditails="" ) const =0; 
    // ...

    static const OnError& IgnoreAll;
    static const OnError& ThrowException;
    static const OnError& Default; // может совпадать с одной из определенных выше переменных. И вообще определяться в run-time.
};


При этом, в run-time могут гулять не только эти две реализации...

Конвертер точно должен быть compile-time, а не run-time?
Просто использование указателей на ns_crap::Fruit compile-time очень ограниченно.

Если нужно получать ссылку на ns_crap::Fruit, то все просто:

template< int VAL >
struct Mapping_int2obj { static const ns_crap::Fruit& obj; };

template<> const ns_crap::Fruit& Mapping_int2obj< ns_val::APPLE     >::obj =::ns_crap::Fruit::Apple     ;
template<> const ns_crap::Fruit& Mapping_int2obj< ns_val::PINEAPPLE >::obj =::ns_crap::Fruit::Pineapple ;
template<> const ns_crap::Fruit& Mapping_int2obj< ns_val::PEAR      >::obj =::ns_crap::Fruit::Pear      ;

Обратно — никак. (Т.е. только в run-time.)
Может все в run-time перевести, упаковав типы из ns_types в boost::variant<...> ?
Re[3]: type converter
От: rg45 СССР  
Дата: 27.09.18 08:27
Оценка: +1
Здравствуйте, SomeOne_TT, Вы писали:

SO_>Изящно, да. Но эти макросы Всегда старался быть от них как можно дальше.

SO_>Впрочем, за неимением гербовой возьму твой способ. Спасибо!

Ну вот, к сожалению, не хватает C++ описательных возможностей. Какждый раз, когда хочется задать декларативное описание каким-то статическим сущностям, неизбежно упираешься в необходимость использования макросов.
--
type converter
От: SomeOne_TT  
Дата: 26.09.18 09:52
Оценка:
Есть три внешние иерархии типов, которые надо маппить друг в друга.

Первая иерархия построена на enum-like int

namespace ns_val
{
    int APPLE = 0
    int PINEAPPLE = 1
    int PEAR = 2
}

Вторая — классические типы
namespace ns_types
{
    struct Apple
    struct Pineapple
    struct Pear
}


Третья — весьма странный (не понимаю, зачем?) способ

namespace ns_crap
{
struct Fruit:Base_Fruit
{
 public:
    static const Fruit& Apple;
    static const Fruit& Pineapple;
    static const Fruit& Pear;
}
}


Задача — написать конвертер, который маппит значение из одной иерархии в другую.
Желаемый интерфейс — что-то вроде

template <...>
struct Mapping
{
    using type = T;
    int   val;
    Fruit obj;
    
}

from_val<ns_val::APPLE>()::type|obj
from_type<ns_types::Pear>()::obj|val
from_crap<ns_crap::Fruit::Pineapple>()::type|val



Что ни придумаю — выходят какие-то уродцы, да еще и ns_crap::Fruit как темплейт аргумент применить невозможно, т.к. это не тип и не значение.
Какие есть варианты?
Отредактировано 26.09.2018 9:55 SomeOne_TT . Предыдущая версия .
Re[2]: type converter
От: rg45 СССР  
Дата: 26.09.18 12:34
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Можно. Это переменная с внешним связыванием, можно параметризовать шаблон указателем на неё


AG>template<ns_crap::Fruit*>

AG>...

Теперь уже можно и ссылкой, не только указателем.
--
Re[2]: type converter
От: SomeOne_TT  
Дата: 26.09.18 12:51
Оценка:
Здравствуйте, Chorkov, Вы писали:

[code]
C>strcut OnError
C>{
C> static const OnError& Default; // может совпадать с одной из определенных выше переменных. И вообще определяться в run-time.
C>};
[/ccode]

C>При этом, в run-time могут гулять не только эти две реализации...


Понятно, спасибо.

C>Конвертер точно должен быть compile-time, а не run-time?

C>Просто использование указателей на ns_crap::Fruit compile-time очень ограниченно.

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

C>Обратно — никак. (Т.е. только в run-time.)

C>Может все в run-time перевести, упаковав типы из ns_types в boost::variant<...> ?

В учебных целях хотелось бы максимально компил-таймово и без повторений кода.
Re[2]: type converter
От: SomeOne_TT  
Дата: 27.09.18 02:41
Оценка:
Здравствуйте, rg45, Вы писали:

R>#define MAKE_MAP_ENTRY(value, type, object) \

R> template <> struct from_val<value> : MapEntry<value, type, object> {}; \
R> template <> struct from_type<type> : MapEntry<value, type, object> {}; \
R> template <> struct from_crap<object> : MapEntry<value, type, object> {};


Изящно, да. Но эти макросы Всегда старался быть от них как можно дальше.
Впрочем, за неимением гербовой возьму твой способ. Спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.