структура из типов
От: Vinick Россия  
Дата: 27.09.06 15:22
Оценка:
Не знаю даже как объяснить по человечески чего я хочу...
Хочу сделать как нибудь так.
namespace draw
{
  template <typename T>
  struct draw_crt
  {
     void operator()(const T & t) const{/*...*/}
  };
  template <typename T>
  struct draw_lcd
  {
     void operator()(const T & t) const{/*...*/}
  };
  template <typename T>
  struct draw_on_printer
  {
    void operator()(const T & t) const{/*...*/}
  };
};

namespace rotate
{
   template <typename T>
   struct rotate_clockwise
   {
      void operator()(T & t) {/*...*/}
   };
   template <typename T>
   struct rotate_counterclockwise
   {
      void operator()(T & t) {/*...*/}
   };
};

template < typename FunctorMap, typename Object>
void draw_and_rotate(Object obj)
{
   typedef FunctorMap::rotator  rotator;
   typedef FunctorMap::drawer   drawer;
   rotator r;
   r(obj);
   drawer d;
   d(obj);
}

int main()
{
 ... 
 FunctorMap fm; // ????
 switch(atoi(argv[1]))
 {
   case 1:
      fm.add_drawer(draw_crt);
      break;
   case 2:
      fm.add_drawer(draw_lcd);
      break;
 };
 switch(atoi(argv[2]))
 {
   case 1:
       fm.add_rotator(rotate_clockwise) ;
       break;
   case 2:
       fm.add_rotator(rotate_counterclockwise) ;
       break;
  };
  Circle c;
  draw_and_rotate</*???*/>(c)
...
}


Получать и устанавливать тип от FunctionMap можно и по индексу....
Т.е нужен такой хитрый compile-runtime полиморфизм.

Можно конечно сделать функторы draw_* и rotate_* унаследованные от абстрактного класа и сделать виртуальный метод, а потом в main
создавать их через new. Но мне так не нравится.

Вопрос 1: Такое вобще реализуемо на C++ ?
Вопрос 2: Может ли тут помочь boost::mpl и как?
Re: структура из типов
От: Кодт Россия  
Дата: 28.09.06 09:18
Оценка:
Здравствуйте, Vinick, Вы писали:

V>Получать и устанавливать тип от FunctionMap можно и по индексу....

V>Т.е нужен такой хитрый compile-runtime полиморфизм.

Где же это compile-time, когда самый что ни на есть run-time.
Такой полиморфизм можно сделать или через виртуальные методы, или через указатели на функции (или, более общо, boost::function).

Но здесь таится другая засада. Тебе нужен не просто полиморфизм, но мультиметоды. Ведь, как я понимаю, FunctorMap должна реализовать шаблон оператора, применяющий все эти полиморфные действия к произвольному типу.

Если бы тип аргумента (Circle) был известен заранее, до конструирования FunctorMap, — то проблем нет.
template<class T>
struct FunctorMap
{
    function< void(*)(T&) > rotate;
    function< void(*)(T&) > draw;
    
    template< template<class> class F > void set_rotate() { rotate = function( F<T>() ); }
    template< template<class> class F > void set_draw()   { draw   = function( F<T>() ); }

    void operator()(T& obj) { rotate(obj); draw(obj); }
};

main()
{
    FunctorMap<Circle> fm;
    fm.set_rotate<rotate_clockwise>();
    fm.set_draw<draw_crt>();
}

А ещё можно пойти функциональным путем
template<template<class>class R, template<class>class D, class T> void doit()
{
    R<T> r;
    D<T> d;
    T t;
    r(t); d(t);
}

template<template<class>class R, template<class>class D> void parse_arg3(char** args)
{
    switch(atoi(args[3]))
    {
    case 1: doit<R,D,Circle>(); break;
    case 2: doit<R,D,Square>(); break;
    ...
    }
}

template<template<class>class R> void parse_arg2(char** args)
{
    switch(atoi(args[2]))
    {
    case 1: parse_arg3<R,draw_on_crt>(args); break;
    case 2: parse_arg3<R,draw_on_ptinter>(args); break;
    ...
    }
}

void parse_arg1(char** args)
{
    switch(atoi(args[1]))
    {
    case 1: parse_arg2<rotate_clockwise>(args); break;
    case 2: parse_arg2<rotate_counterlockwise>(args); break;
    ...
    }
}

Возможно, что как-то попробовать завернуть кортеж типов в mpl_vector...
... << RSDN@Home 1.2.0 alpha rev. 655>>
http://files.rsdn.org/4783/catsmiley.gif Перекуём баги на фичи!
Re: структура из типов
От: Sm0ke Россия ksi
Дата: 28.09.06 11:15
Оценка:
Здравствуйте, Vinick, Вы писали:

Примени паттерн visitor.
Он и есть (compile/run)-time
Re[2]: структура из типов
От: Кодт Россия  
Дата: 28.09.06 12:48
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S>Примени паттерн visitor.

S>Он и есть (compile/run)-time

Кратко, чётко, бесполезно!
Тут вопрос, как именно воплотить этот паттерн.
... << RSDN@Home 1.2.0 alpha rev. 655>>
http://files.rsdn.org/4783/catsmiley.gif Перекуём баги на фичи!
Re[2]: структура из типов
От: Vinick Россия  
Дата: 29.09.06 08:00
Оценка: :)
Здравствуйте, Кодт, Вы писали:

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


V>>Получать и устанавливать тип от FunctionMap можно и по индексу....

V>>Т.е нужен такой хитрый compile-runtime полиморфизм.

К>Где же это compile-time, когда самый что ни на есть run-time.


Вобще-то я надеялся, что будет работать что-то типа такого
struct A {
    void f() { std::cout << "A()" << std::endl; }
};
struct B {
    void f() { std::cout << "B()" << std::endl; }
};
int main()
{
  using namespace boost;
  typedef mpl::map<mpl::pair<mpl::int_<0>,void> > map;
  int i=1;
  if( i ==1 )
    {
      typedef  mpl::insert<map,mpl::pair <mpl::int_<1>, A> >::type map1;
    }
  else
    typedef mpl::insert<map,mpl::pair <mpl::int_<1>,B> >::type map1;

  typedef  mpl::at<map1,mpl::int_<1> >::type S;
  S s;
  s.f();
  return 0;
}

Но судя по всему такое невозможно.


К>Если бы тип аргумента (Circle) был известен заранее, до конструирования FunctorMap, — то проблем нет.

К>
К>template<class T>
К>struct FunctorMap
К>{
К>    function< void(*)(T&) > rotate;
К>    function< void(*)(T&) > draw;
К>

Выяснить тип агрумента заранее можно. Так что видимо я воспользуюсь вашим вариантом.
Re[3]: структура из типов
От: Кодт Россия  
Дата: 29.09.06 09:46
Оценка:
Здравствуйте, Vinick, Вы писали:

V>Вобще-то я надеялся, что будет работать что-то типа такого

V>  if( i ==1 )
V>    typedef mpl::insert<map,mpl::pair <mpl::int_<1>,A> >::type map1;
V>  else
V>    typedef mpl::insert<map,mpl::pair <mpl::int_<1>,B> >::type map1;

V>  typedef  mpl::at<map1,mpl::int_<1> >::type S;

V>Но судя по всему такое невозможно.

Естественно: типы должны определяться во время компиляции. Да и область видимости обоих типов map1 ограничена ветками then и else, а за пределами if ни один из них недоступен.
... << RSDN@Home 1.2.0 alpha rev. 655>>
http://files.rsdn.org/4783/catsmiley.gif Перекуём баги на фичи!
Re[2]: visitor
От: Sm0ke Россия ksi
Дата: 04.10.06 09:51
Оценка:
Одна из реализаций паттерна visitor:

проверено на компиляторе виз. студ.

файл 'visitor.h'
#pragma once

template <class V>
class visitor
{
public:
    template <class T>
    class action
    {
    protected:
        typedef V V;
        typedef T T;
    public:
        static void do_action(V & v, T & target);
    };

    template <class T>
    void operator ()(T & target)
    {
        action<T>::do_action(*static_cast<V *>(this), target);
    }
};


файл 'test_visitor.cpp'
#include "stdafx.h"

#include <iostream>

#include "visitor.h"

class some_visitor :
    public visitor<some_visitor>
{};

class something
{};

void some_visitor::action<something>::do_action(V & v, T & target)
{
    std::wcout << __FUNCTIONW__ << std::endl;
}

void test_visitor()
{
    some_visitor    v;
    something        target;
    v(target);
}


Это упрощённый вариант, работает без виртуальности...
Re[3]: visitor
От: Sm0ke Россия ksi
Дата: 04.10.06 09:53
Оценка:
я использую доработанную версию с виртуальностью.

типа такого:
class part_visitor :
  public _visitor<part_visitor>
{};

class spell_checker :
  public part_visitor::visitor<spell_checker>
{
public:
  wchar_t * h_mem;
  // другие св-ва
};

class part :
  virtual public part_visitor::_is_visitable
{
protected:
  virtual ~part() = 0;
};

class some_part1 :
  public part_visitor::is_visitable<some_part1>
{};

template <>
template <>
template <>
void spell_checker::action<some_part1>::do_action(T & target)
{
  // конкретная реализация действия
}

void test()
{
  part_visitor * hv= new spell_checker(/*параметры*/);
  part * hp= new some_part1;
  hp->visit(hv);
  // удаление hv, hp не забыть!
}


Имена, начинающиеся со знака '_' (с подчёркивания)
это имена интерфейсов.
Re: структура из типов
От: MaximE Великобритания  
Дата: 04.10.06 18:08
Оценка:
Vinick wrote:

> Не знаю даже как объяснить по человечески чего я хочу...

> Хочу сделать как нибудь так.

[]

> Получать и устанавливать тип от FunctionMap можно и по индексу....

> Т.е нужен такой хитрый compile-runtime полиморфизм.
>
> Можно конечно сделать функторы draw_* и rotate_* унаследованные от
> абстрактного класа и сделать виртуальный метод, а потом в main
> создавать их через new. Но мне так не нравится.

В boost::spirit они решают эту же проблему.

http://boost.org/libs/spirit/doc/subrules.html

Spirit is implemented using expression templates. This is a very powerful
technique. Along with its power comes some complications. We almost take for
granted that when we write i | j >> k where i, j and k are all integers the
result is still an integer. Yet, with expression templates, the same expression
i | j >> k where i, j and k are of type T, the result is a complex composite
type [see Basic Concepts]. Spirit expressions, which are combinations of
primitives and composites yield an infinite set of new types. One problem is
that C++ offers no easy facility to deduce the type of an arbitrarily complex
expression that yields a complex type.

...

rule<> r = i | j >> k; // where i, j, and k are chlit<> objects

It might not be apparent but behind the scenes, plain rules are actually
implemented using a pointer to a runtime polymorphic abstract class that holds
the dynamic type of the parser assigned to it. When a Spirit expression is
assigned to a rule, its type is encapsulated in a concrete subclass of the
abstract class. A virtual parse function delegates the parsing to the
encapsulated object.


--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
Re[3]: структура из типов
От: _nn_ www.nemerleweb.com
Дата: 04.10.06 19:03
Оценка:
Здравствуйте, Vinick, Вы писали:

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


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


V>>>Получать и устанавливать тип от FunctionMap можно и по индексу....

V>>>Т.е нужен такой хитрый compile-runtime полиморфизм.

К>>Где же это compile-time, когда самый что ни на есть run-time.


V>Вобще-то я надеялся, что будет работать что-то типа такого

V>
V>struct A {
V>    void f() { std::cout << "A()" << std::endl; }
V>};
V>struct B {
V>    void f() { std::cout << "B()" << std::endl; }
V>};
V>int main()
V>{
V>  using namespace boost;
V>  typedef mpl::map<mpl::pair<mpl::int_<0>,void> > map;
V>  int i=1;
V>  if( i ==1 )
V>    {
V>      typedef  mpl::insert<map,mpl::pair <mpl::int_<1>, A> >::type map1;
V>    }
V>  else
V>    typedef mpl::insert<map,mpl::pair <mpl::int_<1>,B> >::type map1;

V>  typedef  mpl::at<map1,mpl::int_<1> >::type S;
V>  S s;
V>  s.f();
V>  return 0;
V>}
V>

V>Но судя по всему такое невозможно.

Можно сделать по другому:
template<bool Flag, typename T>
struct select_map1_type
{
 typedef typename mpl::insert<T, mpl::pair <mpl::int_<1>, B> >::type type;
};

template<typename T>
struct select_map1_type<false, T>
{
 typedef typename mpl::insert<T, mpl::pair <mpl::int_<1>, A> >::type type;
};

template<bool Flag>
void f_impl()
{
  using namespace boost;
  typedef mpl::map<mpl::pair<mpl::int_<0>,void> > map;
  typedef typename select_map1_type<Flag, map>::type map1;
  typedef typename mpl::at<map1, mpl::int_<1> >::type S;
  S s;
  s.f();
}

void f(bool f)
{
 if(f)
   f_impl<true>();
 else
   f_impl<false>();
}

int main()
{
  using namespace boost;
  int i = 1;
  f(i == 1);
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.