Re[3]: Пропадают методы???
От: MuTPu4  
Дата: 20.06.06 11:24
Оценка: 2 (1)
Здравствуйте, _Dreamer, Вы писали:

_D>мало знаю boost, там по моему есть что то наподобие этого моего enable ? если есть, напомните пожалуйста, как его там зовут

::boost::mpl::if_c.
Еще с точки зрения исходного вопроса может показаться интересной boost.type_traits.integral_promotion. Лично мне бы хотелось там увидеть еще arithmetic_conversions, не такая уж редкая задача, а решается просто и переносимо.
Re: Пропадают методы???
От: Roman Odaisky Украина  
Дата: 20.06.06 08:19
Оценка: +1
Здравствуйте, Lexaux, Вы писали:

L>Мной была избрана следующая тактика — поскольку действия над комплексными числами являются наиболе общими, то класс Complex становится базовым.


“Never derive from concrete classes.”
— Sutter

“Make non-leaf classes abstract.”
— Meyers

Разве сложно сделать это с шаблонами?

template <class XTag, class YTag> struct PromoteTags;

template <> struct PromoteTags<ComplexTag, RealTag> { typedef ComplexTag type; };
template <> struct PromoteTags<IntegerTag, RealTag> { typedef RealTag type; };
...

template <class XType, class YType> struct PromoteReals;

template <> struct PromoteReals<double, float> { typedef double type; };
template <> struct PromoteReals<float, long double> { typedef long double type; };
...

template <class Tag, class Underlying> struct MakeClassFromTag;
template <class Underlying> struct MakeClassFromTag<ComplexTag, Underlying> { typedef Complex<Underlying> type; };
...

template <class Numeric1, class Numeric2>
struct Promote
{
    typedef typename MakeClassFromTag<
        typename PromoteTags<typename Numeric1::Tag, typename Numeric2::Tag>::type,
        typename PromoteReals<typename Numeric1::Underlying, typename Numeric2::Underlying>::type
    >::type type;
};

template <class Numeric1, class Numeric2>
typename Promote<Numeric1, Numeric2>::type someFunc(Numeric1 x, Numeric2 y);

Может, выглядит менее красиво, чем полиморфный вариант, зато быстрее. Дефайны могут помочь в сокращении записи.
До последнего не верил в пирамиду Лебедева.
Пропадают методы???
От: Lexaux Украина  
Дата: 19.06.06 23:51
Оценка:
Здравствуйте, други.
Возникла проблема следующего характера:
при реализации иерархии числовых множеств (Коплексные-Действительный-Целые числа) необходимо было выполнять арифметические действия так, чтобы результат имел тип большего из аргументов.
Мной была избрана следующая тактика — поскольку действия над комплексными числами являются наиболе общими, то класс Complex становится базовым.
От него наследуют "сужающие" множества.
Перегруженные операторы присутствуют во всех классах только для своего уровня, т.е. расширение мы получаем за счет того что класс-сужение является потомком. примерно вот такое код:


// Base class for the numbers
class Complex
{
...
public:
    // operators
    Complex& operator+ (Complex& cmplx){...};
    Complex& operator- (Complex& cmplx);
    Complex& operator* (Complex& cmplx);
    Complex& operator/ (Complex& cmplx);

...

protected:
    // Complex fields
    float real;
    float imag;
...

};



// Real numbers class
class Real : public Complex
{
...
public:
     Real& operator+(Real& value){...};
...

};

А вопрос вот в чем — при попытке потом выполнить такую вот конструкцию —

Complex с(1,2);
Real r(2);
Complex a = c+r;

Все работает. Но если мы ПОМЕНЯЕМ слагаемые местами — перестает. Вот так:
Complex с(1,2);
Real r(2);
Complex a = r+с;

Ошибка при компиляции — "не могу привести тип Complex к типу Real"... То есть оно вызывает новый метод и в упор не видит унаследованного...
Вот...
Я видимо чего то не знаю, я понимал что это 2 разных метода (у них даже сигнатура разная!!!)
Подскажете в чем трабла???
если охота письмо — lexaux(DOG-WOOF-WOOF)gmail.com
СПаСИБО!
------
[ -- the only way out is the way up -- ]
Re: Пропадают методы???
От: _Dreamer Россия  
Дата: 20.06.06 01:57
Оценка:
Здравствуйте, Lexaux, Вы писали:

L>
L>// Base class for the numbers
L>class Complex
L>{
L>...
L>public:
L>    // operators
L>    virtual Complex/* & */ operator+ (const Complex& cmplx){ return Complex( real + cmplx.real, imag + cmplx.imag ) };
L>    virtual Complex/* & */ operator- (const Complex& cmplx);
L>    virtual Complex/* & */ operator* (const Complex& cmplx);
L>    virtual Complex/* & */ operator/ (const Complex& cmplx);

L>...

L>protected:
L>    // Complex fields
L>    float real;
L>    float imag;
L>...

L>};



L>// Real numbers class
L>class Real : public Complex
L>{
L>...
L>public:
L>     using complex::operator+;
L>     Real/* & */ operator+(const Real& value){...};
L>...

L>};
L>


при этих исправления следующий код работает —

Complex c1( 1.0f, 2.0f );
Real r1( 3.0f ), r2(4.0f);

Real r3 = r1 + r2;
Complex c2 = c1 + r2;


либо можно так —

class Complex
{
public :
    Complex( float r_, float i_ ) : r( r_ ), i( i_ ) {}

    friend Complex operator + ( const Complex& lhs, const Complex& rhs );

protected :
    float r, i;
};

class Real : public Complex
{
public :
    Real( float val ) : Complex( val, 0.0f ) {}

    friend Real operator + ( const Real& lhs, const Real& rhs );
};

Complex operator + ( const Complex& lhs, const Complex& rhs )
{
    return Complex( lhs.r + rhs.r, lhs.i + rhs.i );
}

Real operator + ( const Real& lhs, const Real& rhs )
{
    return Real( lhs.r + rhs.r );
}
Re[2]: Пропадают методы???
От: MuTPu4  
Дата: 20.06.06 10:16
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Разве сложно сделать это с шаблонами?


RO>...

RO>Может, выглядит менее красиво, чем полиморфный вариант, зато быстрее. Дефайны могут помочь в сокращении записи.
Небольшое дополнение: уж если необходимо выводить общий тип, то лучше это делать так же, как и встроенные операторы (usual arithmetic conversions). Копирую сюда (5/9) на случай если у автора нет копии стандарта:

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called theusual arithmetic conversions, which are defined as follows:

Re[2]: Пропадают методы???
От: _Dreamer Россия  
Дата: 20.06.06 11:10
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Разве сложно сделать это с шаблонами?

RO>Может, выглядит менее красиво, чем полиморфный вариант, зато быстрее. Дефайны могут помочь в сокращении записи.

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

template < typename ValType >
class complex
{
public :
    typedef ValType value_type;

        template < typename T >
    struct rebind
    {
        typedef complex< T > value;
    };

    complex( ValType r_, ValType i_ ) : r( r_ ), i( i_ ) {}

    //...
protected :
    ValType r, i;
};

template < typename ValType >
class real
{
public :
    typedef ValType value_type;

    template < typename T >
    struct rebind
    {
        typedef real< T > value;
    };

    real( ValType val ) : r( val ) {}

    //...
protected :
    ValType r;
};

template < 
    typename T1, 
    typename T2, 
    bool enable_first = ((sizeof( T1 ) > sizeof( T2 )) || (!std::numeric_limits<T1>::is_integer && std::numeric_limits<T2>::is_integer))
> struct enable
{
    typedef T2 value;
};

template < typename T1, typename T2 > 
struct enable< T1, T2, true >
{
    typedef T1 value;
};

template < typename T1, typename T2 >
struct promote
{
    typedef typename enable< 
        typename T1::value_type, 
        typename T2::value_type 
    >::value max_value_type;

    typedef typename enable<
        typename T1::rebind< max_value_type >::value,
        typename T2::rebind< max_value_type >::value
    >::value value;
};

typedef promote< complex< float >, real< double > >::value type;// тут будет complex< double >
typedef promote< real< float >, real< double > >::value type;// тут будет real< double >


мало знаю boost, там по моему есть что то наподобие этого моего enable ? если есть, напомните пожалуйста, как его там зовут
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.