Войти
ПрограммированиеФорумОбщее

[C++0x,SFINAE] type has a field

Страницы: 1 2 Следующая »
#0
20:52, 9 сен. 2011

Надо проверить есть ли у структуры кое-какое поле(member). Причём всё это надо проделать в compile time.
Вот есть частично неработающий кусок кода.

//User types
struct field_t{};
struct other_t{};
struct StructA{field_t field;};
struct StructB{other_t other;};
struct StructC:public StructA{};
struct StructD:public StructB{};
//Implementation detail
template<typename T,typename FIELD_T>
struct type_has_field{
  typedef char yes_type;
  struct no_type{char padding[8];};
  template<class U>
  static yes_type check_sig1(
    U*,
    FIELD_T(U::*)=&U::field          // !!!Most importantly!!!
  );
  template<class U>
  static no_type check_sig1(...);
  static const bool value=sizeof(check_sig1<T>(0))==sizeof(yes_type);
};
//Experiment
void UnitTest(){
  static_assert(
    false==type_has_field<float,field_t>::value,
    "field_t float::field - should not exist"
  );
  static_assert(
    false==type_has_field<char,field_t>::value,
    "field_t char::field - should not exist"
  );
  static_assert(
    true==type_has_field<StructA,field_t>::value,
    "field_t StructA::field - should exist"
  );
  static_assert(
    false==type_has_field<StructB,field_t>::value,
    "field_t StructB::field - should not exist"
  );
  static_assert(
    true==type_has_field<StructC,field_t>::value,
    "field_t StructC::field - should exist"
  );  
  static_assert(
    false==type_has_field<StructD,field_t>::value,
    "field_t StructD::field - should not exist"
  );
}
void main(){}

Если попытаться это собрать, то мы получим ошибку в строке 16.

"error C2065: field: не объявленный идентификатор"

Собственно промежуточный вопрос: Чем нужно заменить строку 16 чтобы всё заработало?
Этого я думаю для начала хватит.
В следующем посте я напишу чем я попытался это заменить и что из этого вышло.
PS:MSVC2010


added(2013.10.29):
+ решение для MSVC2010

gcc-4.8.1 не поддерживает "__if_exists":
http://ideone.com/pckrBS


#1
21:02, 9 сен. 2011

Попробуй убрать первые два с float-ом и char-ом, у них же "нет поля" field)))

#2
21:25, 9 сен. 2011

vater
С ними нет никакой проблемы, т.к они не являются структурами. Ошибка возникает, когда пытаемся подсунуть структуру у которой нету поля field.

#3
21:30, 9 сен. 2011

vater
> Попробуй убрать первые два с float-ом и char-ом, у них же "нет поля" field)))
там должно быть false а не ошибка компиляции

Adler
у тебя в шаблон передается тип поля, а не имя

#4
21:41, 9 сен. 2011

Pushkoff
AFAIK имя поля или переменной передать через параметр шаблона не возможно в С++0x. Поэтому я зашил имя поля внутри шаблона(см.строку 16).

    FIELD_T(U::*)=&U::field          // !!!Most importantly!!!
#5
21:43, 9 сен. 2011

Adler
да, я прогнал

#6
23:19, 9 сен. 2011

Adler
в поставленном виде задача не имеет решения : )

я обычно чекаю наследование, и если унаследовано, скажем,  от некоего struct IntField { int field; }; то смело вызываю поле field

#7
23:35, 9 сен. 2011

По моему, самое время положить болт. А если это делалось не ради интереса - пересмотреть орхитектуру.

#8
1:42, 10 сен. 2011

Adler
> U::field
такая запись для static'ов наверно катит только

#9
15:01, 10 сен. 2011

berserkovich
Ой ли?

struct A {int field;};
A a;
int A::* p = &A::field;
a.*p = 10;
printf("%d\n", a.*p);
#10
15:40, 10 сен. 2011

Fla
> Ой ли?
любопытно
ну тогда gcc прекрасно справляется с вышеприведённым кодом
http://ideone.com/PwCDW

#11
15:43, 10 сен. 2011

berserkovich
Да проблема то в том, что теста никакого не получается. Как получали ошибку в компил-тайме, что type::field не существует, так и будем получать. Проще просто type::field; написать вместо этого шаблона.

#12
16:03, 10 сен. 2011

Ах да, это все крестопроблемы. Компилятор знает о типах все, что мешает узнать о существовании поля? Я даже согласен на msvs/gcc-specific фичу, не говоря уже о том, что непомешало бы ее включить в стандарт. А то даже STL рвет шаблоны так, что текста на 4 страницы. А нужна всего-лишь маленькая компил-тайм проверка.

#13
16:40, 10 сен. 2011

понял в чём проблема. похоже SFINAE работает только для типов. тогда задача сводится к конструированию типа из T::field и похоже, что она неразрешимая

#14
22:43, 11 сен. 2011

Похоже ничего серьёзного слепить во время компиляции не получится. Ну и ладно, подожду светлого будущего с полноценным отладчиком шаблонов времени компиляции.
Всем спасибо.

Страницы: 1 2 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.