дискриминировать типы, у которых не объявлен подтип
От: cheqa  
Дата: 14.02.13 10:56
Оценка:
Здравия.

Хочется примерно следующего: для типов, у которых есть typedef определённого имени — вызывать один вариант функции, у которых не определён — другой. Что-то вроде enable_if<has_typedef<T::some_type_name>::value>.
Желательно, чтобы работало это так: есть иерархия, в одном из её далёких предков я определяю typedef — и вуаля, машинерия заработала для всех потомков (что-то мне подсказывает, что с этим могут быть проблемы — вроде бы базовые тайпдефы при обработке потомков в шаблонах не учитываются — или я путаю что-то...)

Есть подсказки, как бы это реализовать?
Re: дискриминировать типы, у которых не объявлен подтип
От: Юрий Жмеренецкий ICQ 380412032
Дата: 14.02.13 11:24
Оценка: 8 (2) +1
Здравствуйте, cheqa, Вы писали:

C>Здравия.


C>Хочется примерно следующего: для типов, у которых есть typedef определённого имени — вызывать один вариант функции, у которых не определён — другой. Что-то вроде enable_if<has_typedef<T::some_type_name>::value>.

C>Желательно, чтобы работало это так: есть иерархия, в одном из её далёких предков я определяю typedef — и вуаля, машинерия заработала для всех потомков (что-то мне подсказывает, что с этим могут быть проблемы — вроде бы базовые тайпдефы при обработке потомков в шаблонах не учитываются — или я путаю что-то...)

C>Есть подсказки, как бы это реализовать?


BOOST_MPL_HAS_XXX_TRAIT_DEF
Re: дискриминировать типы, у которых не объявлен подтип
От: Erop Россия  
Дата: 14.02.13 11:37
Оценка: 2 (1)
Здравствуйте, cheqa, Вы писали:

C>Здравия.


C>Хочется примерно следующего: для типов, у которых есть typedef определённого имени — вызывать один вариант функции, у которых не определён — другой. Что-то вроде enable_if<has_typedef<T::some_type_name>::value>.

C>Желательно, чтобы работало это так: есть иерархия, в одном из её далёких предков я определяю typedef — и вуаля, машинерия заработала для всех потомков (что-то мне подсказывает, что с этим могут быть проблемы — вроде бы базовые тайпдефы при обработке потомков в шаблонах не учитываются — или я путаю что-то...)

C>Есть подсказки, как бы это реализовать?


char testIt( ... );
struct char_pair { char first; char second; };
template<typename T>
char_pair testIt( T*, Void<typename T::TriggerType> = Void<typename T::TriggerType>() ) ;

#define HAS_TRIGGER_TYPE( TYPE ) ( sizeof( testIt( (TYPE*)0 ) ) != 1 )
#define OUT_HAS_TRIGGER_TYPE( TYPE ) std::cout << #TYPE " : " << HAS_TRIGGER_TYPE( TYPE ) << std::endl

struct test1{};
struct test2{ typedef int TriggerType; };
struct test3 : test2 {};

int main()
{
    OUT_HAS_TRIGGER_TYPE( test1 );
    OUT_HAS_TRIGGER_TYPE( test2 );
    OUT_HAS_TRIGGER_TYPE( test3 );
    return 0;
}
Оно?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: дискриминировать типы, у которых не объявлен подтип
От: cheqa  
Дата: 14.02.13 12:29
Оценка:
Здравствуйте, Erop, Вы писали:

E>[/c]Оно?


Похоже на то. Благодарствую.
Re[2]: дискриминировать типы, у которых не объявлен подтип
От: rg45 СССР  
Дата: 14.02.13 12:51
Оценка:
Здравствуйте, Erop, Вы писали:

C>>Хочется примерно следующего: для типов, у которых есть typedef определённого имени — вызывать один вариант функции, у которых не определён — другой. Что-то вроде enable_if<has_typedef<T::some_type_name>::value>.

C>>Желательно, чтобы работало это так: есть иерархия, в одном из её далёких предков я определяю typedef — и вуаля, машинерия заработала для всех потомков (что-то мне подсказывает, что с этим могут быть проблемы — вроде бы базовые тайпдефы при обработке потомков в шаблонах не учитываются — или я путаю что-то...)

C>>Есть подсказки, как бы это реализовать?


E>
char testIt( ... );
E>struct char_pair { char first; char second; };
E>template<typename T>
E>char_pair testIt( T*, Void<typename T::TriggerType> = Void<typename T::TriggerType>() ) ;

E>#define HAS_TRIGGER_TYPE( TYPE ) ( sizeof( testIt( (TYPE*)0 ) ) != 1 )
E>#define OUT_HAS_TRIGGER_TYPE( TYPE ) std::cout << #TYPE " : " << HAS_TRIGGER_TYPE( TYPE ) << std::endl

E>struct test1{};
E>struct test2{ typedef int TriggerType; };
E>struct test3 : test2 {};

E>int main()
E>{
E>    OUT_HAS_TRIGGER_TYPE( test1 );
E>    OUT_HAS_TRIGGER_TYPE( test2 );
E>    OUT_HAS_TRIGGER_TYPE( test3 );
E>    return 0;
E>}
E>
Оно?


Вопрос чисто академический: можно ли усовершенствовать это решение, что бы оно работало (хотя бы компилировалось), когда доступ к TriggerType закрыт (либо он объявлен как private/protected, либо кто-то из потомков использует закрытое наследование)?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: дискриминировать типы, у которых не объявлен подтип
От: Roman Odaisky Украина  
Дата: 14.02.13 13:21
Оценка: 7 (2)
Здравствуйте, rg45, Вы писали:

R>Вопрос чисто академический: можно ли усовершенствовать это решение, что бы оно работало (хотя бы компилировалось), когда доступ к TriggerType закрыт (либо он объявлен как private/protected, либо кто-то из потомков использует закрытое наследование)?


В C++11 должно работать благодаря новой редакции 14.8.2/8, см. http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1170
До последнего не верил в пирамиду Лебедева.
Re[3]: дискриминировать типы, у которых не объявлен подтип
От: Erop Россия  
Дата: 14.02.13 14:47
Оценка:
Здравствуйте, rg45, Вы писали:

R>Вопрос чисто академический: можно ли усовершенствовать это решение, что бы оно работало (хотя бы компилировалось), когда доступ к TriggerType закрыт (либо он объявлен как private/protected, либо кто-то из потомков использует закрытое наследование)?


Для typedef, скорее всего нельзя.
А вот для поля, скорее всего можно. Для этого надо параметризовать Void указателем на поле...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: дискриминировать типы, у которых не объявлен подтип
От: Шахтер Интернет  
Дата: 14.02.13 14:58
Оценка:
Здравствуйте, cheqa, Вы писали:

C>Здравия.


C>Хочется примерно следующего: для типов, у которых есть typedef определённого имени — вызывать один вариант функции, у которых не определён — другой. Что-то вроде enable_if<has_typedef<T::some_type_name>::value>.

C>Желательно, чтобы работало это так: есть иерархия, в одном из её далёких предков я определяю typedef — и вуаля, машинерия заработала для всех потомков (что-то мне подсказывает, что с этим могут быть проблемы — вроде бы базовые тайпдефы при обработке потомков в шаблонах не учитываются — или я путаю что-то...)

C>Есть подсказки, как бы это реализовать?


В CCore это реализовано вот так (пример).


/* struct ProbeSet_ArrayAlgoType */

struct ProbeSet_ArrayAlgoType
 {
  template <class T> struct Host;
  
  template <class T>
  static constexpr bool Probe(...) { return false; }
  
  template <class T>
  static constexpr bool Probe(Host<typename T::ArrayAlgoType> *) { return true; } // К сожалению, имя не может быть параметром шаблона.
 };

/* struct Has_ArrayAlgoType<T> */ 

template <class T> 
struct Has_ArrayAlgoType : Meta::Has<T,ProbeSet_ArrayAlgoType> {};


Has_ArrayAlgoType<T>::Ret даёт ответ на вопрос о существовании в классе внутреннего типа ArrayAlgoType.

Воспомогательная мета-функция.

/* struct Has<T,ProbeSet> */

template <class T,class ProbeSet> 
struct Meta::Has
 {
  enum RetType { Ret = ProbeSet::template Probe<T>(0) };
 };
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: дискриминировать типы, у которых не объявлен подтип
От: Шахтер Интернет  
Дата: 14.02.13 15:10
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, rg45, Вы писали:


R>>Вопрос чисто академический: можно ли усовершенствовать это решение, что бы оно работало (хотя бы компилировалось), когда доступ к TriggerType закрыт (либо он объявлен как private/protected, либо кто-то из потомков использует закрытое наследование)?


RO>В C++11 должно работать благодаря новой редакции 14.8.2/8, см. http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1170


gcc 4.7.1 работает по-старому.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: дискриминировать типы, у которых не объявлен подтип
От: Serg27  
Дата: 15.02.13 02:11
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>
char testIt( ... );
E>struct char_pair { char first; char second; };
E>template<typename T>
E>char_pair testIt( T*, Void<typename T::TriggerType> = Void<typename T::TriggerType>() ) ;
E>....
E>
Оно?


Чтоб не тратить лишние секунды на понимание кода, лучше добавить определение Void в начало:

template <typename T> struct Void {};
Re[3]: дискриминировать типы, у которых не объявлен подтип
От: Erop Россия  
Дата: 15.02.13 04:58
Оценка:
Здравствуйте, Serg27, Вы писали:

S>Чтоб не тратить лишние секунды на понимание кода, лучше добавить определение Void в начало:


S>
S>template <typename T> struct Void {};
S>



Да, конесно же лучше. Просто при копи-пасте промазал.
Прошу прощения.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: дискриминировать типы, у которых не объявлен подтип
От: Кодт Россия  
Дата: 15.02.13 08:25
Оценка:
Здравствуйте, Erop, Вы писали:

E>
E>char testIt( ... );
E>struct char_pair { char first; char second; };
E>template<typename T>
E>char_pair testIt( T*, Void<typename T::TriggerType> = Void<typename T::TriggerType>() ) ;

E>#define HAS_TRIGGER_TYPE( TYPE ) ( sizeof( testIt( (TYPE*)0 ) ) != 1 )
E>


Любишь магические типы, или просто торопился и поленился?
typedef char yes_type;
typeder char (&no_type)[2];

template<typename T> yes_type testIt(blablabla);
no_type(...);

#define HAS_TRIGGER_TYPE(T) (sizeof(testIt((T*)0))==sizeof(yes_type))
Перекуём баги на фичи!
Re[3]: дискриминировать типы, у которых не объявлен подтип
От: Erop Россия  
Дата: 15.02.13 08:33
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Любишь магические типы, или просто торопился и поленился?

просто считаю, что так понятнее и короче.
В смысле, no_type заводить лень, а yes_type без no заводить странно.
Ну и ссылка на массив менее понятна, чем структура из двух чаров. Это же пример, что бы обхяснить, а не ребус...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: дискриминировать типы, у которых не объявлен подтип
От: Erop Россия  
Дата: 15.02.13 08:38
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Любишь магические типы, или просто торопился и поленился?

К>
К>typedef char yes_type;
К>typeder char (&no_type)[2];
К>



Кроме того, если честно, мне ID no_type вообще не нравится. Я его читаю, как "нет типа".

Возможно понятнее всего было бы написать так:
template<int N>struct nChar { char Body[N]; };
nChar<1> testIt( ... );
nChar<2> testIt( blablabla );


Но мне кажется, что я и так уже достаточно просто и доходчиво передал идею. Это пусть Лаптев думает, как надо идеально это писать с методической точки зрения...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: дискриминировать типы, у которых не объявлен подтип
От: Кодт Россия  
Дата: 15.02.13 18:12
Оценка:
Здравствуйте, Erop, Вы писали:

К>>Любишь магические типы, или просто торопился и поленился?

E>просто считаю, что так понятнее и короче.

Насчёт короче — да. Насчёт понятнее — прямая аналогия с магическими числами.

E>В смысле, no_type заводить лень, а yes_type без no заводить странно.


Для демо-кода их можно вообще не объявлять, а оставлять за скобками. В конце концов, именно эти два типа уже объявлены в бусте.

E>Ну и ссылка на массив менее понятна, чем структура из двух чаров. Это же пример, что бы обхяснить, а не ребус...


Издевательское инфиксное объявление функции char (&testIt(arguments go here))[2]; — безусловно менее понятно.
Перекуём баги на фичи!
Re[4]: дискриминировать типы, у которых не объявлен подтип
От: Кодт Россия  
Дата: 15.02.13 18:16
Оценка: +1 :))
Здравствуйте, Erop, Вы писали:

E>Кроме того, если честно, мне ID no_type вообще не нравится. Я его читаю, как "нет типа".


Это ж всё в контексте познаётся. Рядом с yes_type прочитать неправильно — сложновато. Опять же, устоявшаяся идиома.

E>Возможно понятнее всего было бы написать так:
template<int N>struct nChar { char Body[N]; };
E>nChar<1> testIt( ... );
E>nChar<2> testIt( blablabla );


Если дискриминация не да-нет, а так-этак-растак-никак, то годный подход!

E>Но мне кажется, что я и так уже достаточно просто и доходчиво передал идею. Это пусть Лаптев думает, как надо идеально это писать с методической точки зрения...


Запомню отмазку. Ну, Лаптев, берегись!
Перекуём баги на фичи!
Re[5]: дискриминировать типы, у которых не объявлен подтип
От: Erop Россия  
Дата: 15.02.13 18:27
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Для демо-кода их можно вообще не объявлять, а оставлять за скобками. В конце концов, именно эти два типа уже объявлены в бусте.


может и можно, но мне кажется, что так понятнее..

К>Издевательское инфиксное объявление функции char (&testIt(arguments go here))[2]; — безусловно менее понятно.


А я такого и не писал, хотя мог бы...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: дискриминировать типы, у которых не объявлен подтип
От: Шахтер Интернет  
Дата: 15.02.13 18:37
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Но мне кажется, что я и так уже достаточно просто и доходчиво передал идею. Это пусть Лаптев думает, как надо идеально это писать с методической точки зрения...


С "методической точки зрения" лучше использовать constexpr и возвращать true и false.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: дискриминировать типы, у которых не объявлен подтип
От: sokel Россия  
Дата: 16.02.13 22:39
Оценка:
Здравствуйте, Erop, Вы писали:

E>Кроме того, если честно, мне ID no_type вообще не нравится. Я его читаю, как "нет типа".


E>Возможно понятнее всего было бы написать так: [c]template<int N>struct nChar { char Body[N]; };


Хм... я частенько делаю частичную специализацию функций через такой вот примерно шаблон:

template<bool> class t_bool   {};
typedef t_bool<true> t_true;
typedef t_bool<false> t_false;

...

template<bool foo_supported>
class A
{
  void foo() { foo(t_bool<foo_supported>()); }
  void foo(t_false) { } // dummy
  void foo(t_true) // foo implementation
  {


Надо бы сделать t_true/t_false специализациями с разным размером, тогда их можно и для таких проверок использовать.
Re[5]: дискриминировать типы, у которых не объявлен подтип
От: Erop Россия  
Дата: 17.02.13 07:08
Оценка:
Здравствуйте, sokel, Вы писали:

S>
S>template<bool F> class t_bool   { char dummy[F+1]; enum {Value = F}; };
S>


S>Надо бы сделать t_true/t_false специализациями с разным размером, тогда их можно и для таких проверок использовать.


Зачем специализациями-то?..

На самом деле можно сделать всё ровно наоборот. сделать
t_int<int>
и
typedef t_int<true> t_true;
typedef t_int<false> t_false;
Или там t_value, например, назвать...

Тогда можно будет не только по bool, но и по знаениям enum перегрузку делать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.