С точки зрения пользователей вашей оболочки, лучше всего было бы, если бы они вызывали либо перегруженную функцию, либо шаблон функции (члена), которому они передают объект соответствующего типа, и который затем волшебным образом делает то, что нужно для этого. тип. То есть лучше всего было бы иметь функцию getData(unsigned int colIndex, T&) для любого типа T, поддерживаемого вашим классом (или Oracle API), который узнает необходимый размер буфера, выделит буфер, определит правильное перечисление и вызовет функцию Oracle API .
Я уверен, что вы сможете проработать большинство деталей, возможно, за исключением того, как сопоставить тип с enum, поэтому я попытаюсь обрисовать именно это.
По сути, я вижу две возможности для этого, одна из которых (использование списка времени компиляции) лучше подходит, если у вас есть много поддерживаемых типов, а другая (использование трейтов) необходимо использовать, если есть более специфичные для типа к этому, чем просто сопоставление типа с enum.
Метод признаков довольно прост в использовании, но утомителен, если у вас много типов:
template<typename T>
struct get_data_buffer_traits;
template<>
struct get_data_buffer_traits<int> {
Type type OCCIINT;
};
template<>
struct get_data_buffer_traits<float> {
Type type OCCIBFLOAT;
};
Затем вы можете сопоставить тип, переданный вашему шаблону как T, с правильным значением enum, используя get_data_buffer_traits<T>::type.
Этот шаблон признаков также является местом, где вы можете поместить любую другую операцию, специфичную для типа, которая может понадобиться вашей универсальной функции извлечения данных (например, преобразование между тем, что находится в буфере, и фактическим типом, если это не прямое приведение). Если вам больше нечего добавить в эти трейты, вы можете использовать макрос, чтобы упростить их определение:
#define DEFINE_GET_DATA_BUFFER_TRAITS(Type_,Enum_) \
template<> struct get_data_buffer_traits<Type_> { Type type Enum_; };
DEFINE_GET_DATA_BUFFER_TRAITS(int , OCCIINT );
DEFINE_GET_DATA_BUFFER_TRAITS(float, OCCIBFLOAT);
...
#undef DEFINE_GET_DATA_BUFFER_TRAITS
Однако, если это так, вы также можете создать карту времени компиляции, которая сопоставляет их два, и искать (во время компиляции) правильное значение enum. Если у вас нет под рукой метабиблиотеки шаблонов, которая обеспечивает это, вот набросок идеи, как сделать это самостоятельно:
// Beware, brain-compiled code ahead!
struct nil {};
template< typename HType
, Type HEnum
, class T >
struct set_data_buffer_type_map_node {
typedef HType head_type
enum { head_enum = HEnum };
typedef T tail_type;
};
typedef
set_data_buffer_type_map_node< int , OCCIINT
set_data_buffer_type_map_node< float, OCCIBFLOAT
...
nil
> > // either count or keep adding these until compiler accepts :)
set_data_buffer_type_map;
template< typename T, class Map >
struct getter {
// recurse towards tail
Type get_enum() { return getter<T,typename Map::tail_type>::get_enum(); }
};
template< typename T, Type HEnum, class Tail >
struct getter< T, set_data_buffer_type_map<T,HEnum,Tail> > {
// current node has T as HType
Type get_enum() { return set_data_buffer_type_map<T,HEnum,Tail>::head_enum; }
};
template< typename T, typename HType, Type HEnum, >
struct getter< T, set_data_buffer_type_map<T,HEnum,nil> > {
// no function here, so compile-time error
};
template< typename T>
Type get_type_enum()
{
return getter<T, set_data_buffer_type_map>::get_enum();
}
(Примечание: это всего лишь набросок. Я даже не пытался его компилировать.)
person
sbi
schedule
05.04.2011