Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > определить, есть ли у объекта конкретный метод


Автор: boostcoder 1.5.2011, 15:57
всем привет.

пишу свою поделку сериализации.
сериализацию POD`ов и STL типов реализовал.
остался реализовать сериализацию пользовательских типов.

т.е., сейчас пользователь для своего типа должен реализовать такое:
Код

struct user_type {
   int x;
   int y;
};

...

dy::binary_oarchive oa;
user_type ut;

oa & ut;


но такого способа недостаточно. т.к. возможно потребуется сериализация приватных свойств класса.
для этого, нужно чтоб юзер в своем классе реализовал публичный метод serialize(). и это не проблема.
проблема в том, как заставить сериализатор определять, есть ли этот метод у объекта, и если есть, вызвать его?

т.е. в таком случае, user_type должен быть таким:
Код

struct user_type {
   template<typename Archive>
   void serialize(Archive& ar) {
      ar & x
         & y;
   }
private:
   int x;
   int y;
};



просьба не отсылать смотреть исходники boost.serialization. смотрел. запутался и ничего не понял.

спасибо.

Автор: rudvil 1.5.2011, 16:14
http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence/257382
Странно, на LWS не работает...
http://liveworkspace.org/code/f620e0ce438c5e9f1a7880a962a10d77
хотя у меня на компе все ок, mingw-4.6.0

Автор: boostcoder 1.5.2011, 17:03
rudvil, спасибо.
перешел по ссылке: http://www.rsdn.ru/forum/cpp/2759773.1.aspx
просвещаюсь..

а почему код не работает, я не понимаю.. вроде бы все законно.

Автор: mes 1.5.2011, 17:08
Цитата(rudvil @  1.5.2011,  15:14 Найти цитируемый пост)
Странно, на LWS не работает...

так как typeof нестандартный оператор, и работает только при каких то там опциях... 

Цитата(boostcoder @  1.5.2011,  16:03 Найти цитируемый пост)
а почему код не работает, я не понимаю.. вроде бы все законно. 

небольшое изменение и все компилится :
http://liveworkspace.org/code/6c3ddb994de1bcfbf9cf34da757f33a9
smile

Автор: boostcoder 1.5.2011, 17:19
Цитата(mes @  1.5.2011,  17:08 Найти цитируемый пост)
так как typeof нестандартный оператор, и работает только при каких то там опциях...

буду знать.

Цитата(mes @  1.5.2011,  17:08 Найти цитируемый пост)
небольшое изменение и все компилится

и правда smile

Автор: boostcoder 2.5.2011, 13:22
конечный код:
Код

#include <iostream>

namespace detail {

template<typename Type>
struct has_member {
private:
   class yes { char m; };
   class no { yes m[2]; };

   struct BaseMixin {
      void func(){}
   };

   struct Base: Type, BaseMixin {};

   template<typename T, T t>
   class Helper {};

   template<typename U>
   static no deduce(U*, Helper<void (BaseMixin::*)(), &U::func>* = 0);
   static yes deduce(...);

public:
   enum { value = sizeof(yes) == sizeof(deduce((Base*)(0))) };
};

template <typename>
struct void_exp_result
{};

//Перегрузка оператора запятая 'operator,'
template <typename T, typename U>
U const& operator,(U const&, void_exp_result<T>);

template <typename T, typename U>
U& operator,(U&, void_exp_result<T>);

template <typename T1, typename T2>
struct clone_constness {
   typedef T2 type;
};

template <typename T1, typename T2>
struct clone_constness<const T1, T2> {
   typedef const T2 type;
};

} // namespace detail

template<typename Object, typename Sig>
struct has_member {
private:
   class yes {};
   class no { yes m[2]; };

   //добавляем перегруженный метод
   struct derived: public Object {
      using Object::func;
      no func(...) const; 
   };

   //Учтем возможную константность типа класса
   typedef typename detail::clone_constness<Object, derived>::type derived_type;

   //Проверка результата выражения
   template <typename T, typename due_type>
   struct return_value_check {
      static yes deduce(due_type);
      static no deduce(...);
      //явные перегрузки в случае, если
      //due_type имеет шаблонный конструктор
      static no deduce(no);                              
      static no deduce(detail::void_exp_result<Object>);
   };

   //Проверка результата выражения в случае,
   //если не интересует возвращаемый тип метода
   template <typename T>
   struct return_value_check<T, void> {
      static yes deduce(...);
      static no deduce(no);
   };

   template <bool has, typename F>
   struct impl {
      enum { value = false };
   };

   template <typename Arg1, typename r>
   struct impl<true, r(Arg1)> {
      enum { value = sizeof(
            return_value_check<Object, r>::deduce(
               (((derived_type*)0)->func(
                  *(Arg1*)0
               ), detail::void_exp_result<Object>())
            )
         ) == sizeof(yes)
      };
   };
   template <typename Arg1, typename Arg2, typename r>
   struct impl<true, r(Arg1, Arg2)> {
      enum { value = sizeof(
            return_value_check<Object, r>::deduce(
               (((derived_type*)0)->func(
                  *(Arg1*)0,
                  *(Arg2*)0
               ), detail::void_exp_result<Object>())
            )
         ) == sizeof(yes)
      };
   };

public:
   //сначала проверяем наличие метода с помощью has_member
   enum { value = impl<detail::has_member<Object>::value, Sig>::value };
};

/***************************************************************************/

struct With {
   void func(int) const {}
};

struct WithTemplate {
   template <typename T>
   void func(T){}
};

struct Without {};

int main() {
   std::cout << has_member<With, void(int)>::value << std::endl;
   std::cout << has_member<WithTemplate, void(int)>::value << std::endl;
   std::cout << has_member<Without, void(int)>::value << std::endl;
    
   return 0;
}

http://liveworkspace.org/code/5f8fb487c260dad214dcaeed9db17305

всем спасибо.

Автор: mes 2.5.2011, 14:34
Цитата(boostcoder @  2.5.2011,  12:22 Найти цитируемый пост)
конечный код:

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

Автор: boostcoder 2.5.2011, 14:49
Цитата(mes @  2.5.2011,  14:34 Найти цитируемый пост)
осталось задефайнить

ага.

все таки, с++ забавный ЯП. главное что не унылый, т.к. постоянно что-то новое узнаешь... и так наверное без конца...
не помню в какой книжке и какого автора, но он писал о том, что с++ не создавался для того чтоб при его использовании можно было писать метапрограммы. метапрограммирование в с++ _открыли_ позже. smile

Автор: mes 3.5.2011, 02:32
Цитата(boostcoder @  2.5.2011,  13:49 Найти цитируемый пост)
не помню в какой книжке и какого автора, но он писал 

Цитата

In C++, it was discovered almost by accident, that the template mechanism provides a rich facility for computation at compile-time.

http://www.boost.org/doc/libs/1_31_0/libs/mpl/doc/paper/html/intro.html
smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)