Re[4]: Инициализация массива члена класса
От: Sabrian  
Дата: 01.02.06 17:11
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Про смарт-поинтеры и хэндлы — как над ними производить математические расчеты?

Не непосредственно над ними, а над типами которые они инкапсулируют.
И кроме того есть еще всякие матрицы, поверхности плоскости — прямые... И сами векторы к тому же, хотя тут проблемы нет.
Кроме того у меня специализирован

template< class T, unsigned N >
class vect< T&, N >;

эдакая вектор-ссылка
Благодаря этому есть поддержка swizzling'a

vect< double, 3 > a(1,2,3), b(4,5,6);

a.zyx() = b.xxx();

Но что-б компилировалось
vect< vect< int&, 3 >, 4 > мне пришлось добавить в vect< T&, N > конструктор по умолчанию( должен быть только копирования и поэлементной инициализации, для сохранения семантики вектора ссылок ), тат как С — style массив требует наличия такового у класса элемента.
И кроме того — я просто не хочу себя ограниивать.
Re[7]: выравнен ли sizeof?
От: Sabrian  
Дата: 01.02.06 17:20
Оценка:
Здравствуйте, Erop, Вы писали:

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


B>>>Т.е. непонятно, в чем разница м\д union above и таким

B>>>
B>>>union {
B>>>    char data[3 * sizeof(T)];
B>>>} u;
B>>>


BF>>Допустим, архитектура компьютера позволяет иметь char по любому адресу, а к примеру, int должен быть выровнян по 4 байтам (то есть его адрес должен делится на 4). Тогда делая reinterpret_cast<int*>(u.data) и разыменовывая этот указатель -- мы получим аппаратное исключение. Обычная реакция оси на такие исключния -- убийство процесса..



E>Всё бы ничего, но разве вот sizeof не обязан быть кратен выравниванию типа?

E>Вроде как такие вот фокусы совершенно portable должны быть:

E>
E>class T .... {
E>    ...
E>    T& GetNextInVector() { return this[1]; }
E>    ....
E>};
E>


E>или я что-то пропустил?


Это то конечно ок. Но только если this получен легально. На стеке лежит или возвращен менеджером памяти. В union this может лечь как глюк на душу положит... вернее смотря как char ляжет...
Re[8]: выравнен ли sizeof?
От: Sabrian  
Дата: 02.02.06 15:11
Оценка:
Получилось вот так:


template< unsigned A, unsigned B >
struct trait_min
{
    enum { result = A < B ? A : B };
};

template< class T >
struct trait_aligment_helper
{
    char c;
    T t;
};

template< class T >
struct trait_aligment
{
    enum { align = trait_min< sizeof(trait_aligment_helper<T>) - sizeof(T), sizeof(T) >::result };
};


template< class U, class V, bool F >
struct trait_type_switch
{
private:
    
    template< bool F >
    struct trait_alternative
    {
        typedef U switched;
    };

    template<>
    struct trait_alternative<true>
    {
        typedef V switched;
    };

public:
    
    typedef typename trait_alternative<F>::switched result;

};

struct trait_empty
{};

template< unsigned A, unsigned MAX_SIZE >
struct trait_type_with_align
{
private:
    class C
    {};
    
    class base1
    {};

    class base2
    {};

    class M: public base1, public base2
    {};

    class V: public virtual C
    {};

    class H: public virtual C, public M, public V
    {};
    
public:
    typedef typename trait_type_switch< 
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch<
            typename trait_type_switch< trait_empty,
                     int C::*    , trait_aligment<int C::*    >::align == A && sizeof(int C::*    ) <= MAX_SIZE >::result, 
                     int M::*    , trait_aligment<int M::*    >::align == A && sizeof(int M::*    ) <= MAX_SIZE >::result, 
                     int V::*    , trait_aligment<int V::*    >::align == A && sizeof(int V::*    ) <= MAX_SIZE >::result, 
                     int H::*    , trait_aligment<int H::*    >::align == A && sizeof(int H::*    ) <= MAX_SIZE >::result, 
                     void(C::*)(), trait_aligment<void(C::*)()>::align == A && sizeof(void(C::*)()) <= MAX_SIZE >::result, 
                     void(M::*)(), trait_aligment<void(M::*)()>::align == A && sizeof(void(M::*)()) <= MAX_SIZE >::result, 
                     void(V::*)(), trait_aligment<void(V::*)()>::align == A && sizeof(void(V::*)()) <= MAX_SIZE >::result, 
                     void(H::*)(), trait_aligment<void(H::*)()>::align == A && sizeof(void(H::*)()) <= MAX_SIZE >::result, 
                     void(*)(),    trait_aligment<void(*)()   >::align == A && sizeof(void(*)()   ) <= MAX_SIZE >::result, 
                     void*,           trait_aligment<void*          >::align == A && sizeof(void*          ) <= MAX_SIZE >::result, 
                     long double,  trait_aligment<long double >::align == A && sizeof(long double ) <= MAX_SIZE >::result, 
                     double,       trait_aligment<double      >::align == A && sizeof(double      ) <= MAX_SIZE >::result, 
                     float,           trait_aligment<float          >::align == A && sizeof(float       ) <= MAX_SIZE >::result, 
                     long int,       trait_aligment<long int    >::align == A && sizeof(long int    ) <= MAX_SIZE >::result, 
                     short,           trait_aligment<short          >::align == A && sizeof(short       ) <= MAX_SIZE >::result, 
                     char,           trait_aligment<char        >::align == A && sizeof(char        ) <= MAX_SIZE >::result,
                     long,           trait_aligment<long        >::align == A && sizeof(long        ) <= MAX_SIZE >::result,
                     int,           trait_aligment<int         >::align == A && sizeof(int         ) <= MAX_SIZE >::result result;
};                    

template< class T, unsigned N >
struct aligned_buffer
{
    enum { align = trait_aligment<T>::align };
    
    union
    {
        char buffer[N];
        typename trait_type_with_align< trait_aligment<T>::align, sizeof(T) * N >::result aligned_type;
    };

    inline T* data()
    {
        return (T*)(buffer);
    }

    inline const T* data() const
    {
        return (const T*)(buffer);
    }

};


Теперь можно использовать

   
   aligned_buffer< double, 10 > buff;
   buff.data()[3] = 1.0;


Кстати я нашел ошибку в boost::type_traits::aligned_storage. При определении типа с требуемым выравниванием, в boost не проверяются указатели на методы классов с множественным и виртуальгным наследованием, хотя в многих компиляторах размер и выравнивание указателей на методы отличаются. Например в MSVC 7.1 обычный указатель на метод 4 байта, с множественным наследованием 8, а с виртуальным 12. aligned_storage этот факт упрямо игнорирует.
Re[9]: выравнен ли sizeof?
От: MaximE Великобритания  
Дата: 02.02.06 15:38
Оценка:
On Thu, 02 Feb 2006 15:11:37 -0000, Sabrian <50840@users.rsdn.ru> wrote:

> Получилось вот так:

>
>
>


Для платформ, на которых работает linux, код определения максимального выравнивания можно упростить до:

size_t const max_align = 2 * sizeof(size_t);


malloc.c из glibc-2.3.5

Alignment: 2 * sizeof(size_t) (default)
(i.e., 8 byte alignment with 4byte size_t). This suffices for
nearly all current machines and C compilers. However, you can
define MALLOC_ALIGNMENT to be wider than this if necessary.


--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re[9]: выравнен ли sizeof?
От: Sabrian  
Дата: 02.02.06 15:40
Оценка:
Ошибочка.

template< class T, unsigned N >
struct aligned_buffer
{
    enum { align = trait_aligment<T>::align };
    
    union
    {
        char buffer[N * sizeof(T)];
        typename trait_type_with_align< trait_aligment<T>::align, sizeof(T) * N >::result aligned_type;
    };

    inline T* data()
    {
        return (T*)(buffer);
    }

    inline const T* data() const
    {
        return (const T*)(buffer);
    }

};
Re[3]: Инициализация массива члена класса
От: Sm0ke Россия ksi
Дата: 09.02.06 13:56
Оценка:
Если объект класса создаётся в указанной области памяти то как его правильно удалять?
Или просто для него деструктор вызвать.
Читал в мсдн 2к5, про new есть, про delete не нашёл.
Re[4]: Инициализация массива члена класса
От: Sabrian  
Дата: 09.02.06 18:11
Оценка: 2 (1)
Здравствуйте, Sm0ke, Вы писали:

S>Если объект класса создаётся в указанной области памяти то как его правильно удалять?

S>Или просто для него деструктор вызвать.
Да, просто вызвать ему деструктор.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.