Re: Включение одной функции в несколько классов
От: Кодт Россия  
Дата: 06.06.08 15:50
Оценка: 2 (1)
Здравствуйте, Andrew001, Вы писали:

A>Есть некая функция которую нужно сделать элементом нескольких классов

A>1 — это сделать родительский класс в котором и объявить эту функция
A>2 — это сделать глобальную функцию к которой обращаться из промежуточных функций-членов этих классов
A>Оба эти варианта не очень подходят
A>Какие еще есть варианты?
A>Возможно ли это сделать через шаблоны?

Можно сделать миксин (класс-примесь) и добавить его с помощью идиомы CRTP во все интересующие классы
// CRTP-заготовка для всех миксинов
template<class T>
struct mixin
{
    T& self() { return static_cast<T&>(*this); }
    T const& self() const { return static_cast<T&>(*this); }
};

// наш миксин, реализующий функцию foo
// это паттерн проектирования "Шаблонный метод"
// только без виртуальности, а на полиморфизме времени компиляции
template<class T>
struct foo_mixin : mixin<T>
{
    void foo()
    {
        this->self().bar(); // this-> нужен для того, чтобы искать имя self в контексте класса, а не где попало
        this->self().buz(); // хотя VC к этому относится терпимее, чем comeau
    }
};

// нахлобучиваем миксин на наш класс
class A : public foo_mixin<A>
{
private:
    friend class foo_mixin<A>;
    void bar();
    void buz();
public:
};

///////////////////////////////////////////////
// или вот так ещё

template<class T>
struct foo_object : T
{
    void foo()
    {
        this->bar();
        this->buz();
    }
};

class B_proto
{
public:
    void bar();
    void buz();
};
// нахлобучиваем миксин поверх класса-прототипа
typedef foo_object<B_proto> B;


//////////////////////////////////////////////////
// окончательно разнесём миксин и прототип

// foo_object можно сделать и так
template<class T, template<class>class Mixin>
struct object : T, Mixin< object<T,Mixin> >
{};

typedef object<B_proto, foo_mixin> C;


int main()
{
    A().foo();
    B().foo();
    C().foo();
}
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: Включение одной функции в несколько классов
От: Andrew001  
Дата: 07.06.08 13:55
Оценка: :)
template<class T> bool aaaaaaaaaaa(T* p);

class bbb
{
public:
bool aabbcc() { return false; }

bool abc() { return aaaaaaaaaaa(this); }
};

class ccc
{
public:
bool aabbcc() { return false; }

bool abc() { return aaaaaaaaaaa(this); }
};

template<class T> bool aaaaaaaaaaa(T* p)
{
return p->aabbcc();
}

Сам спросил,и сам себе же ответил
Всем откликнувшимся большое спасибо
Включение одной функции в несколько классов
От: Andrew001  
Дата: 06.06.08 15:00
Оценка:
Есть некая функция которую нужно сделать элементом нескольких классов
1 — это сделать родительский класс в котором и объявить эту функция
2 — это сделать глобальную функцию к которой обращаться из промежуточных функций-членов этих классов
Оба эти варианта не очень подходят
Какие еще есть варианты?
Возможно ли это сделать через шаблоны?
Re: Включение одной функции в несколько классов
От: rg45 СССР  
Дата: 06.06.08 15:38
Оценка:
Здравствуйте, Andrew001, Вы писали:

A>Есть некая функция которую нужно сделать элементом нескольких классов

A>1 — это сделать родительский класс в котором и объявить эту функция
A>2 — это сделать глобальную функцию к которой обращаться из промежуточных функций-членов этих классов
A>Оба эти варианта не очень подходят
A>Какие еще есть варианты?
A>Возможно ли это сделать через шаблоны?

Возможно, например:
#include <iostream>
#include <string>

template<typename T, typename V>
void set_value(T& item, const V& value)
{
  item.value = value;
}

struct A
{
  int value;
};

struct B
{
  std::string value;
};


int main() 
{
  A a;
  B b;
  
  set_value(a, 123);
  set_value(b, "hello");
  
  std::cout << a.value << std::endl; //output: "123"
  std::cout << b.value << std::endl; //output: "hello"
}
--
Re[2]: Включение одной функции в несколько классов
От: Andrew001  
Дата: 06.06.08 15:49
Оценка:
Здравствуйте, rg45, Вы писали:

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


A>>Есть некая функция которую нужно сделать элементом нескольких классов

A>>1 — это сделать родительский класс в котором и объявить эту функция
A>>2 — это сделать глобальную функцию к которой обращаться из промежуточных функций-членов этих классов
A>>Оба эти варианта не очень подходят
A>>Какие еще есть варианты?
A>>Возможно ли это сделать через шаблоны?

R>Возможно, например:

R>
R>#include <iostream>
R>#include <string>

R>template<typename T, typename V>
R>void set_value(T& item, const V& value)
R>{
R>  item.value = value;
R>}

R>struct A
R>{
R>  int value;
R>};

R>struct B
R>{
R>  std::string value;
R>};


R>int main() 
R>{
R>  A a;
R>  B b;
  
R>  set_value(a, 123);
R>  set_value(b, "hello");
  
R>  std::cout << a.value << std::endl; //output: "123"
R>  std::cout << b.value << std::endl; //output: "hello"
R>}
R>



нужно чтобы вызов остался прежним
a.set_value(...)
b.set_value(...)

Нет ли какойто возможности типа:
template<typename T>
void T::set_value(...)

ну а в классах:
class A
{
void set_value(...);
};

class B
{
void set_value(...);
};
Re[3]: Включение одной функции в несколько классов
От: Кодт Россия  
Дата: 07.06.08 14:33
Оценка:
Здравствуйте, Andrew001, Вы писали:

A>Сам спросил,и сам себе же ответил


У тебя в каждом классе кусочек копипаста.
    bool abc() { return aaaaaa(this); }

Хорошо, когда он простой. Можно объявить макрос и вставить его в объявление каждого класса.
#define IMPLEMENT_ABC() bool abc() { return aaaaaa(this); }

class A
{
    ...
    IMPLEMENT_ABC()
};

class B
{
    ...
    IMPLEMENT_ABC()
};


Для более сложных случаев миксин лучше делать не из макроса, а из шаблона — CRTP или наследник, по вкусу.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.