Привет,
Есть C API работу с которым хочется обернуть т.к. для использования API надо выполнить некоторые рутинные вещи. Проблема в том, параметр в виде структуры передающиеся в функцию-обёртку могут иметь, а могут не иметь некоторых полей для заполнения, следовательно, нужно выбирать алгоритмы с разными рутинами. Я осилил создание шаблона HasField для проверки наличия поля в структуре честно сперев его на SO и не разобравщись как оно работает , но не понимаю как это использовать для выбора алгоритма.
Как я себе это представляю
Скрытый текст
далее идёт код курильшика
template<typename T, typename = void>
struct HasField_abc : std::false_type { };
template<typename T>
struct HasField_abc<T, decltype(std::declval<T>().abc, void())> : std::true_type { };
template<typename T, typename U = HasField_abc<T>::value>
void get(T& value);
// да, я понимю что частичная специализация не применимаtemplate<typename T, std::true_type>
void get(T& value);
{
// поле есть
value.abc = c_api_do_stuff();
c_api_get(value);
}
template<typename T, std::false_type>
void get(T& value);
{
// поля нет
c_api_get(value);
}
Хочется увидеть код здорового человека. Нужен С++11, желательно чтобы был совместим с C++0x, т.е. поддержка не очень свежим gcc.
Здравствуйте, Kernan, Вы писали:
K>Привет, K>Есть C API работу с которым хочется обернуть т.к. для использования API надо выполнить некоторые рутинные вещи. Проблема в том, параметр в виде структуры передающиеся в функцию-обёртку могут иметь, а могут не иметь некоторых полей для заполнения, следовательно, нужно выбирать алгоритмы с разными рутинами. Я осилил создание шаблона HasField для проверки наличия поля в структуре честно сперев его на SO и не разобравщись как оно работает , но не понимаю как это использовать для выбора алгоритма.
Здравствуйте, Kernan, Вы писали: K>Привет, K>Есть C API работу с которым хочется обернуть т.к. для использования API надо выполнить некоторые рутинные вещи. Проблема в том, параметр в виде структуры передающиеся в функцию-обёртку могут иметь, а могут не иметь некоторых полей для заполнения, следовательно, нужно выбирать алгоритмы с разными рутинами. Я осилил создание шаблона HasField для проверки наличия поля в структуре честно сперев его на SO и не разобравщись как оно работает , но не понимаю как это использовать для выбора алгоритма. K>Как я себе это представляю
cut
K>
Скрытый текст
далее идёт код курильшика
K>
K>template<typename T, typename = void>
K>struct HasField_abc : std::false_type { };
K>template<typename T>
K>struct HasField_abc<T, decltype(std::declval<T>().abc, void())> : std::true_type { };
K>template<typename T, typename U = HasField_abc<T>::value>
K>void get(T& value);
K>// да, я понимю что частичная специализация не применима
K>template<typename T, std::true_type>
K>void get(T& value);
K>{
K> // поле есть
K> value.abc = c_api_do_stuff();
K> c_api_get(value);
K>}
K>template<typename T, std::false_type>
K>void get(T& value);
K>{
K> // поля нет
K> c_api_get(value);
K>}
K>
K>Хочется увидеть код здорового человека. Нужен С++11, желательно чтобы был совместим с C++0x, т.е. поддержка не очень свежим gcc.
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, Kernan, Вы писали:
K>>Привет, K>>Есть C API работу с которым хочется обернуть т.к. для использования API надо выполнить некоторые рутинные вещи. Проблема в том, параметр в виде структуры передающиеся в функцию-обёртку могут иметь, а могут не иметь некоторых полей для заполнения, следовательно, нужно выбирать алгоритмы с разными рутинами. Я осилил создание шаблона HasField для проверки наличия поля в структуре честно сперев его на SO и не разобравщись как оно работает , но не понимаю как это использовать для выбора алгоритма.
_>А что мешает для конкретных стуктур описать? _>
Как это работает?
A>Если компилятор поддерживает, можешь std::enable_if_t вместо std::enable_if использовать.
Вроде поддерживает, но как оно будет потом пока не ясно.
Здравствуйте, Kernan, Вы писали:
K>Привет, K>Есть C API работу с которым хочется обернуть т.к. для использования API надо выполнить некоторые рутинные вещи. Проблема в том, параметр в виде структуры передающиеся в функцию-обёртку могут иметь, а могут не иметь некоторых полей для заполнения, следовательно, нужно выбирать алгоритмы с разными рутинами. Я осилил создание шаблона HasField для проверки наличия поля в структуре честно сперев его на SO и не разобравщись как оно работает , но не понимаю как это использовать для выбора алгоритма. K>... K>Хочется увидеть код здорового человека. Нужен С++11, желательно чтобы был совместим с C++0x, т.е. поддержка не очень свежим gcc.
Для не очень свежего gcc, возможно, придется использовать std::enable_if вместо std::enable_if_t, ну или определить собственный аналог для компактности кода.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Kernan, Вы писали:
K>Здравствуйте, kov_serg, Вы писали:
_>>Здравствуйте, Kernan, Вы писали:
K>>>Привет, K>>>Есть C API работу с которым хочется обернуть т.к. для использования API надо выполнить некоторые рутинные вещи. Проблема в том, параметр в виде структуры передающиеся в функцию-обёртку могут иметь, а могут не иметь некоторых полей для заполнения, следовательно, нужно выбирать алгоритмы с разными рутинами. Я осилил создание шаблона HasField для проверки наличия поля в структуре честно сперев его на SO и не разобравщись как оно работает , но не понимаю как это использовать для выбора алгоритма.
_>>А что мешает для конкретных стуктур описать? _>>
K>Количество структур, у меня их за 20 штук и могут появится новые. Я бы не парился так если бы из было 2-3
Невижу проблем 20 не 20000. И потом можно сделать генератор.
http://en.cppreference.com/w/cpp/language/sfinae
Если есть член, компилятор сгенерит одно определение функции, а второе не сможет и выкинет функцию из множества перегрузок. Ну и если нет члена — то будет обратное, только выкинет первое определение.
Здравствуйте, Kernan, Вы писали:
K>Как это работает?
Погугли по аббревиатуре SFINAE (Substitution Failure Is Not An Error). Мы разобрали только один частный случай применения этой идиомы, тогда как сценариев ее исползования существенно больше.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, swingus, Вы писали:
S>Из соображений скорости компиляции разумнее сделать tag dispatch'ем:
S>Здравствуйте, Kernan, Вы писали:
Скорее всего как-то так и сделаю. Проблема в том, что решение от rg45 традиционно не взлетело.
Здравствуйте, Kernan, Вы писали:
K>Здравствуйте, swingus, Вы писали:
S>>Из соображений скорости компиляции разумнее сделать tag dispatch'ем:
S>>Здравствуйте, Kernan, Вы писали: K>Скорее всего как-то так и сделаю. Проблема в том, что решение от rg45 традиционно не взлетело.
На обычном C++ можно как-то так написать
#include <stdio.h>
#define MAYSET(name) \
template<class T> class Has_##name { \
struct A { int name; }; \
struct B : T,A {}; \
template<typename C,C> struct D; \
template<class C> static double test(D<int A::*,&C::name>*); \
template<class C> static char test(...); \
public: \
enum { value = sizeof(test<B>(0))==sizeof(char) }; \
}; \
template<class T,class V> void mayset_##name(T *t,V v,char(*)[!Has_##name<T>::value]=0) {} \
template<class T,class V> void mayset_##name(T *t,V v,char(*)[Has_##name<T>::value]=0) { \
t->name=v; \
printf("set "#name"=%d\n",(int)v); /* для проверки */ \
}
MAYSET(x)
struct A { int x; } a[1];
struct B { int y; } b[1];
int main(int argc,char**argv) {
mayset_x(a,10);
mayset_x(b,20);
return 0;
}
Здравствуйте, Kernan, Вы писали:
K>Проблема в том, что решение от rg45 традиционно не взлетело.
Что именно не взлетело, ты пытался разобраться? Вот это же решение с минимальными изменениями нормально работает тоже на gcc в рамках С++11: http://cpp.sh/7sen.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Что именно не взлетело?
В 11 нет enable_if_t (я нашёл реализацию на SO от нашего коллеги Abyx), но даже после этого компилятор выкидывает из поиска не то, что нужно. Может это бага компилятора.
Здравствуйте, Kernan, Вы писали:
K>Здравствуйте, rg45, Вы писали:
R>>Что именно не взлетело? K>В 11 нет enable_if_t (я нашёл реализацию на SO от нашего коллеги Abyx), но даже после этого компилятор выкидывает из поиска не то, что нужно. Может это бага компилятора.
Так я тебе об этом сразу написал в том же сообщении:
Для не очень свежего gcc, возможно, придется использовать std::enable_if вместо std::enable_if_t, ну или определить собственный аналог для компактности кода.
Релизация enable_if_t тривиальна:
template <bool cond, typename type = void>
using enable_if_t = typename std::enable_if<cond, type>::type;
--
Не можешь достичь желаемого — пожелай достигнутого.