Как такое починить на MSVC?
От: Cruelty  
Дата: 04.01.10 15:20
Оценка: 38 (2)
gcc компилирует этот код и все работает.

#include <iostream>
#include <string>

struct C
{
    std::string b;    
};

template <typename Type, Type> struct Helper;
template <typename T, typename Type> char Finder(Helper<Type, &T::b>*);

int main()
{
    std::cout << sizeof(Finder<C, std::string C::*>(0)) << std::endl;
}


Как такое починить на MSVC? Что интересно, если std::string в обоих местах поменять на, скажем int, то все работает и в MSVC.
Re: Как такое починить на MSVC?
От: Cruelty  
Дата: 04.01.10 18:26
Оценка: 7 (1)
Суть всего этого упражнения для меня определить существует ли член класса с определённым именем и определенного типа. Этакая интроспекция автогенерённых классов.

И ещё один вопрос, может кто знает существует ли способ написать такой Helper класс:
struct A;
struct B
{
    A* a;
};

Helper<B>::type is the same as struct A


У меня как-то совсем никаких идей нет как это сделать...
Re: Как такое починить на MSVC?
От: Кодт Россия  
Дата: 04.01.10 19:26
Оценка:
Здравствуйте, Cruelty, Вы писали:

Прекрасно! Очередной баг в VC.
VC8 вываливается в ICE, если ему разжевать по буквам и подсунуть вот такой код
//typedef int X;
struct X {};

struct C
{
    X b;    
};

template <typename PtrType, PtrType PtrValue> struct Helper {};
template <typename HostType, typename DataType> char Finder(Helper<DataType HostType::*, &HostType::b>*);

int main()
{
    Helper<X C::*, &C::b> h;
    Finder(&h);
}

Надо будет проверить на VC9...
Перекуём баги на фичи!
Re[2]: Как такое починить на MSVC?
От: rg45 СССР  
Дата: 04.01.10 19:55
Оценка:
Здравствуйте, Cruelty, Вы писали:

C>Суть всего этого упражнения для меня определить существует ли член класса с определённым именем и определенного типа. Этакая интроспекция автогенерённых классов.


C>И ещё один вопрос, может кто знает существует ли способ написать такой Helper класс:

C>
C>struct A;
C>struct B
C>{
C>    A* a;
C>};

C>Helper<B>::type is the same as struct A
C>


C>У меня как-то совсем никаких идей нет как это сделать...


Было дело, с похожим "уравнением" я пыли наглотался, убил уйму времени... короче, у меня не получилось
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: Как такое починить на MSVC?
От: SleepyDrago Украина  
Дата: 05.01.10 10:00
Оценка: :)
Здравствуйте, Кодт, Вы писали:

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


К>Прекрасно! Очередной баг в VC.

К>VC8 вываливается в ICE, если ему разжевать по буквам и подсунуть вот такой код
К>
К>//typedef int X;
К>struct X {};

К>struct C
К>{
К>    X b;    
К>};

К>template <typename PtrType, PtrType PtrValue> struct Helper {};
К>template <typename HostType, typename DataType> char Finder(Helper<DataType HostType::*, &HostType::b>*);

К>int main()
К>{
К>    Helper<X C::*, &C::b> h;
К>    Finder(&h);
К>}
К>

К>Надо будет проверить на VC9...

Да что там могло улучшиться — Access violation в компиляторе как и следовало ожидать

ps. Надо будет проверить VC10b2 ...
Re[2]: Как такое починить на MSVC?
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 05.01.10 12:20
Оценка:
Здравствуйте, Cruelty, Вы писали:

C>Суть всего этого упражнения для меня определить существует ли член класса с определённым именем и определенного типа. Этакая интроспекция автогенерённых классов.


C>И ещё один вопрос, может кто знает существует ли способ написать такой Helper класс:

C>
C>struct A;
C>struct B
C>{
C>    A* a;
C>};

C>Helper<B>::type is the same as struct A
C>


C>У меня как-то совсем никаких идей нет как это сделать...

это должно работать для любого призвольного класса? или допускаются вспомогательные метаданные, если второе то у меня получалось
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[3]: Как такое починить на MSVC?
От: Cruelty  
Дата: 05.01.10 13:41
Оценка:
Здравствуйте, ollv, Вы писали:

O> это должно работать для любого призвольного класса? или допускаются вспомогательные метаданные, если второе то у меня получалось


Here I know type B and member name a. I want to deduce type A.
Any solution is more than welcome as at the very least it may bring some fresh ideas to consideration. Cheers
Re[4]: Как такое починить на MSVC?
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 05.01.10 15:19
Оценка: 4 (1)
Здравствуйте, Cruelty, Вы писали:

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


O>> это должно работать для любого призвольного класса? или допускаются вспомогательные метаданные, если второе то у меня получалось


C>Here I know type B and member name a. I want to deduce type A.

C>Any solution is more than welcome as at the very least it may bring some fresh ideas to consideration. Cheers
So.. this sample with macros using realization in vc
 
namespace fl
{
struct yes_type{ char _[1]; };
struct no_type { char _[8]; };
struct _Empty;

template<typename _Cur, typename _Next>
   struct item_type0 {  typedef _Cur cur_type; typedef _Next type_next;  };

template <typename _Ty>
   yes_type _Is_regged_func(typename _Ty::_Is_registered_tag* ptr= 0);

template <typename _Ty>
   no_type _Is_regged_func(...);

template <typename _Ty>
   struct _Is_registered { static const int value = (sizeof(_Is_regged_func<_Ty>()) == sizeof(yes_type));  };

template <typename _Ty, typename _Branch = struct _New_branch >
   struct _Get_fields
{
   template <int _I=1, int _Is_regged = _Is_registered<_Ty::fields_storage<_I> > >
      struct _Iterator   
    {
            typedef item_type0<typename _Ty::fields_storage<_I>::field_type, typename _Iterator<_I+1>::result > result;       
            static const int count = _Iterator<_I+1>::count;
        };

   template <int _I >
      struct _Iterator<_I, 0>   
    {
            typedef _Empty result;       
            static const int count = _I;
        };

   typedef _Iterator<>::result result;
   static const int count = _Iterator<>::count;

};

#define serrialization(_Class) typedef _Class this_class;   template <int _I>     struct fields_storage;

#define decl_field(type, ident) type ident; \
   struct field_tag_##ident \
{  \
   typedef type result_type; typedef type this_class::*TypeField; \
   static TypeField field(){ return &this_class::ident; } \
};\
template <>\
    struct fields_storage<_Get_fields<this_class, field_tag_##ident >::count > { typedef field_tag_##ident field_type; };


}
 
struct some_class 
{
   serrialization(some_class);

   decl_field(int,m_A);
   decl_field(std::string, m_B);
};

int main()
{
    typedef fl::_Get_fields<some_class>::result fields;
    //there are we look typelist with metadata fields .. ^) thanks 
    print_type(fields);   
}

But i don't have compiler in home, then i quick write but, don't compile this primitive sample ..but, this tehnology worked for auto binding iterabled fields , half step on hybernate in c++ and etc ^))
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[5]: Как такое починить на MSVC?
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 05.01.10 15:23
Оценка:
Здравствуйте, ollv, Вы писали:

Млин в вордпаде не напишешься .. в общем после выхода на работу прихвачу рабочий код ..
оверквотинг удалён, и пожалуйста, так и продолжайте дискуссию на русском языке. — Кодт
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[5]: Забыл еще одну вещь..
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 05.01.10 16:02
Оценка:
Здравствуйте, ollv, Вы писали:

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


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


O>>> это должно работать для любого призвольного класса? или допускаются вспомогательные метаданные, если второе то у меня получалось


C>>Here I know type B and member name a. I want to deduce type A.

C>>Any solution is more than welcome as at the very least it may bring some fresh ideas to consideration. Cheers
O>So.. this sample with macros using realization in vc
O>
 
O>namespace fl
O>{
O>struct yes_type{ char _[1]; };
O>struct no_type { char _[8]; };
O>struct _Empty;

O>template<typename _Cur, typename _Next>
O>   struct item_type0 {  typedef _Cur cur_type; typedef _Next type_next;  };

O>template <typename _Ty>
O>   yes_type _Is_regged_func(typename _Ty::_Is_registered_tag* ptr= 0);

O>template <typename _Ty>
O>   no_type _Is_regged_func(...);

O>template <typename _Ty>
O>   struct _Is_registered { static const int value = (sizeof(_Is_regged_func<_Ty>()) == sizeof(yes_type));  };

O>template <typename _Ty, typename _Branch = struct _New_branch >
O>   struct _Get_fields
O>{
O>   template <int _I=1, int _Is_regged = _Is_registered<_Ty::fields_storage<_I> > >
O>      struct _Iterator   
O>    {
O>            typedef item_type0<typename _Ty::fields_storage<_I>::field_type, typename _Iterator<_I+1>::result > result;       
O>            static const int count = _Iterator<_I+1>::count;
O>        };

O>   template <int _I >
O>      struct _Iterator<_I, 0>   
O>    {
O>            typedef _Empty result;       
O>            static const int count = _I;
O>        };

O>   typedef _Iterator<>::result result;
O>   static const int count = _Iterator<>::count;

O>};

O>#define serrialization(_Class) typedef _Class this_class;   template <int _I>     struct fields_storage;

O>#define decl_field(type, ident) type ident; \
O>   struct field_tag_##ident \
O>{  \
O>   typedef type result_type; typedef type this_class::*TypeField; \
O>   static TypeField field(){ return &this_class::ident; } \
O>};\
template <>\
    struct fields_storage<_Get_fields<this_class, field_tag_##ident >::count >\
 { struct _Is_registered_tag{}; typedef field_tag_##ident field_type; };


O>}
 
O>struct some_class 
O>{
O>   serrialization(some_class);

O>   decl_field(int,m_A);
O>   decl_field(std::string, m_B);
O>};

O>int main()
O>{
O>    typedef fl::_Get_fields<some_class>::result fields;
O>    //there are we look typelist with metadata fields .. ^) thanks 
O>    print_type(fields);   
O>}

O>

O> But i don't have compiler in home, then i quick write but, don't compile this primitive sample ..but, this tehnology worked for auto binding iterabled fields , half step on hybernate in c++ and etc ^))
struct registered_tag{}; -флаг зареганности филды
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[6]: Забыл еще одну вещь..
От: Cruelty  
Дата: 06.01.10 16:36
Оценка:
Здравствуйте, ollv, Вы писали:

O>struct registered_tag{}; -флаг зареганности филды


Это, к сожалению, немного не то. Суть в том, что мне нельзя модифицировать автогенерированные классы, поетому регистрацию членов класса не получится сделать.
Re[2]: Как такое починить на MSVC?
От: Caracrist https://1pwd.org/
Дата: 06.01.10 17:40
Оценка:
Здравствуйте, Cruelty, Вы писали:

C>Суть всего этого упражнения для меня определить существует ли член класса с определённым именем и определенного типа. Этакая интроспекция автогенерённых классов.


C>И ещё один вопрос, может кто знает существует ли способ написать такой Helper класс:

C>
C>struct A;
C>struct B
C>{
C>    A* a;
C>};

C>Helper<B>::type is the same as struct A
C>


C>У меня как-то совсем никаких идей нет как это сделать...


если в рантайм, то можно так:

struct A8 {};
struct A9 : A8 {};
struct B8
{
    A8* a;
};
template<typename T>
struct Helper
{
    typedef T type ;
};

template<typename T>
struct IsSame
{
    template<typename T2> static bool As(T2*, T *) {return true;}
    static bool As(void *, void *) {return false;}
    template<typename T2> static bool As()
    {return  As((T2*)0,(T2*)0);}
};
template<typename T1, typename T2> 
bool AreSame()
{
    return IsSame<T1>::As<T2>() && IsSame<T2>::As<T1>();
}

int main()
{
    bool testik = AreSame<A9,Helper<A8>::type>();
    bool testik0 = AreSame<A8,Helper<A8>::type>();
    bool testik1 = IsSame<A9>::As<Helper<A8>::type>();
    bool testik2 = IsSame<Helper<A8>::type>::As<A9>();
        cout << testik << endl << testik0 << endl << testik1 << endl << testik2 << endl;
        return 0;
}

~~~~~
~lol~~
~~~ Single Password Solution
Re[3]: Как такое починить на MSVC?
От: Caracrist https://1pwd.org/
Дата: 07.01.10 06:54
Оценка:
Вот полная реализация.

template<bool ok> struct IsDerrived{};
template<bool ok> struct InterDerrived{};
template<typename T> struct Derrived
{
    template<typename T2> 
    static IsDerrived<true> From(T2*, T *) {return IsDerrived<true>();}
    static IsDerrived<false> From(void *, void *) {return IsDerrived<false>();}
};
template<bool derrived, bool base>
InterDerrived<derrived && base> TestInterDerrived(IsDerrived<derrived>, IsDerrived<base>) {return InterDerrived<derrived && base>();}
#define AreInterDerrived(T1, T2) TestInterDerrived(Derrived<T1>::From((T2*)0,(T2*)0), Derrived<T2>::From((T1*)0,(T1*)0))


теперь можно писать отдельные функции для случаев с одинаковыми типами и для случаев с разными, компилятор разберётся...


// example functions 
template<typename T1, typename T2> 
void func(T1 p1, T2 p2, void * extra, InterDerrived<true>)
{
}
template<typename T1, typename T2> 
void func(T1 p1, T2 p2, void * extra, InterDerrived<false>)
{
}
template<typename T1, typename T2> 
void func(T1 p1, T2 p2, void * extra)
{
func(p1, p2, extra, AreInterDerrived(T1,T2));
}

// use 
struct C { typedef int T; T v;};
struct A { struct A1 { typedef int T; }; A1::T v; };
template<typename T> 
struct B { typedef T TT; TT v;};

void Some(void * extData)
{
A a = A();
B<char> b = B<char>();
C c = C();
func(a.v, c.v, extData);
func(b.v, c.v, extData);
func(a.v, b.v, extData);
}

~~~~~
~lol~~
~~~ Single Password Solution
Re[4]: Как такое починить на MSVC?
От: Cruelty  
Дата: 07.01.10 10:04
Оценка:
Здравствуйте, Caracrist,

Please correct me if I am wrong, but this seems to verify whether a class derived from another class, rather then deduce the type of class' member by its name.

Also, isn't this fuctionality available in boost.TypeTraits library (is_base_of/is_same)?
Re[5]: Как такое починить на MSVC?
От: Caracrist https://1pwd.org/
Дата: 07.01.10 10:23
Оценка:
Здравствуйте, Cruelty, Вы писали:

C>Здравствуйте, Caracrist,


C>Please correct me if I am wrong, but this seems to verify whether a class derived from another class, rather then deduce the type of class' member by its name.


C>Also, isn't this fuctionality available in boost.TypeTraits library (is_base_of/is_same)?


Да, не поинтересовался. Дают тот же результат.
Учитывая то, что тебе об этом известно, я, скорее всего, не правильно понял вопрос.
~~~~~
~lol~~
~~~ Single Password Solution
Re[7]: Забыл еще одну вещь..
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 11.01.10 09:14
Оценка: 4 (1)
Здравствуйте, Cruelty, Вы писали:

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


O>>struct registered_tag{}; -флаг зареганности филды


C>Это, к сожалению, немного не то. Суть в том, что мне нельзя модифицировать автогенерированные классы, поетому регистрацию членов класса не получится сделать.

раскрой суть автогенеренных классов. Если классы нельзя модифицировать(код класса), т.е. сторонняя библиотека тот-же трюк можно проделать через внешний аксессор
template <typename _Ty>
  struct _Accessor;

class A {  public:  int m_A;  };

//псевдокод
template<>
  struct _Accessor<A>
{
   ...
   decl_field(int, &A::m_A);
};

автоматизировать построение таких аксессоров на пребилдевете в студии. И с полями можно будет работать как с обычным списком значений... или нельзя модифицировать из-за константности — тогда реализовать конструктор принимающий мультитайплист
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[8]: Забыл еще одну вещь..
От: Cruelty  
Дата: 11.01.10 18:08
Оценка: 1 (1) +1
Здравствуйте, ollv, Вы писали:

O> раскрой суть автогенеренных классов. Если классы нельзя модифицировать(код класса), т.е. сторонняя библиотека тот-же трюк можно проделать через внешний аксессор

O> автоматизировать построение таких аксессоров на пребилдевете в студии. И с полями можно будет работать как с обычным списком значений... или нельзя модифицировать из-за константности — тогда реализовать конструктор принимающий мультитайплист

Модифицировать авто-генерённые классы -- себя не любить. Они же могут и перегенериться.

Твой подход по сути эквивалентен type traits, только немного более нестандартный. Пока что я реализовал все используя простые рабоче-крестьянские type traits, но хотелось бы найти общее решение, чтобы поддержка новых классов не требовала добавления нового кода.
Re[9]: Забыл еще одну вещь..
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 12.01.10 21:47
Оценка:
Здравствуйте, Cruelty, Вы писали:

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


O>> раскрой суть автогенеренных классов. Если классы нельзя модифицировать(код класса), т.е. сторонняя библиотека тот-же трюк можно проделать через внешний аксессор

O>> автоматизировать построение таких аксессоров на пребилдевете в студии. И с полями можно будет работать как с обычным списком значений... или нельзя модифицировать из-за константности — тогда реализовать конструктор принимающий мультитайплист

C>Модифицировать авто-генерённые классы -- себя не любить. Они же могут и перегенериться.


C>Твой подход по сути эквивалентен type traits, только немного более нестандартный. Пока что я реализовал все используя простые рабоче-крестьянские type traits, но хотелось бы найти общее решение, чтобы поддержка новых классов не требовала добавления нового кода.

да если не автоматизировать постгенерейт на пребилд евенте(или автогенерация происходит по-другому?), то это будет проблемой
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re: Как такое починить на MSVC?
От: D14  
Дата: 17.01.10 12:02
Оценка: 12 (1)
Здравствуйте, Cruelty, Вы писали:


C>Как такое починить на MSVC? Что интересно, если std::string в обоих местах поменять на, скажем int, то все работает и в MSVC.


#include <iostream>
#include <string>

struct Yes{int i;};
struct No{Yes i[10];};


template< typename T,typename R > No Helper(...); 
template< typename T,typename R > Yes Helper(R (T::* t)); 

template< typename T,typename R >
struct Finder
{
enum {value=(sizeof(Helper<T,R>(&T::b)) == sizeof(Yes))};
};


struct A { int b; }; 
struct B { char b; }; 
struct C { std::string b; }; 

int main()
{

    std::cout << Finder<A,int>::value << std::endl;
    std::cout << Finder<B,int>::value << std::endl;
    std::cout << Finder<C,std::string>::value << std::endl;
}

Вывод:
1
0
1
Re[2]: Как такое починить на MSVC?
От: Cruelty  
Дата: 19.01.10 11:41
Оценка:
Здравствуйте, D14, Вы писали:

Splendid!

This approach can be extended to methods easily:


#include <iostream>
#include <string>

struct Yes{int i;};
struct No{Yes i[10];};


template< typename T,typename R > No Helper(...); 
template< typename T,typename R > Yes Helper(R (T::*)); 
template< typename T,typename R > Yes Helper(R); 

template< typename T,typename R >
struct Finder
{
    enum {value=(sizeof(Helper<T,R>(&T::b)) == sizeof(Yes))};
};


struct A { int b; }; 
struct B { char b; }; 
struct C { std::string b; }; 
struct D { int b(int) const; };
struct E { int (*b)(int); };

int main()
{
    std::cout << Finder<A, int>::value << std::endl;
    std::cout << Finder<B, char>::value << std::endl;
    std::cout << Finder<C, std::string>::value << std::endl;
    std::cout << Finder<D, int (D::*)(int) const>::value << std::endl;
    std::cout << Finder<E, int (*)(int)>::value << std::endl;

    std::cout << Finder<A, int (*)()>::value << std::endl;
    std::cout << Finder<B, int>::value << std::endl;
    std::cout << Finder<C, B>::value << std::endl;
    std::cout << Finder<D, int (D::*)(int)>::value << std::endl;
    std::cout << Finder<E, int (E::*)(int)>::value << std::endl;
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.