Здравствуйте, 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 массив требует наличия такового у класса элемента.
И кроме того — я просто не хочу себя ограниивать.
Здравствуйте, 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 ляжет...
Получилось вот так:
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 этот факт упрямо игнорирует.
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 YegorushkinPosted via RSDN NNTP Server 2.0
Ошибочка.
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);
}
};
Если объект класса создаётся в указанной области памяти то как его правильно удалять?
Или просто для него деструктор вызвать.
Читал в мсдн 2к5, про new есть, про delete не нашёл.