Re[14]: sizeof(array) in template
От: Denn  
Дата: 20.02.03 18:40
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ> Но вот функциональные типы по-прежнему проскальзывают сквозь слишком широкую дыру:


Думаю, проще будет определить функциональный тип, чем удачно прикрыть на "пациенте"...

А я пока про вторую часть исходной задачи, определить размер. Все бы просто, но есть типы int[] и т.п. Которые, признаются полноценными массивами.
Мое решение:


template<class U> class ArrayLenght {
    template<class T>
       static    T & GetType(T*);    // Обретение type[] размеров.
    static U * make();
    enum {value = sizeof( GetType(make()) ) / sizeof( **make() )   };
};

template<class T>
class Capacity {

template<bool C = true >
struct IF {
    enum { value = ArrayLenght<T>::value };
};

template<>
struct IF<false> {
    enum { value = 0 };
};

public:
    enum {value = IF< ArrayTester<T>::value >::value };

};


Ключевой прием согласуется со стандартом? Если нет, то очень интересны Ваши решения!!!

PS: Так навороченно из-за того, что sizeof(int[]) невычислим...
Re[13]: sizeof(array) in template
От: Denn  
Дата: 21.02.03 14:39
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ> легко исправляется так:


АТ>
АТ>template<typename T_> struct is_array
АТ>{
АТ>  static char (&is(const void*))[2];
АТ>  static char (&is(...))[1];
АТ>  static T_* ret(); 
АТ>  enum { value = (sizeof(is(*ret())) - 1) && is_array_<T_>::value };
АТ>};
АТ>


А тогда is_array<int &> и прочие ссылки компилиться не будут.

Может написать выбирающий шаблон, который будет контролировать типы допустимые для возврата в нашем контексте?
С void легко разобраться, а вот с определением ссылки уже не так просто (пользуясь пересечением стандарта и MS)...
Так же, очень интересно удаление ссылки и указателя без использования частичной специализации.

А вобщем, еще раз повторюсь, это классное решение задачи
Re[13]: sizeof(array) in template
От: Denn  
Дата: 21.02.03 15:36
Оценка:
Предлагаю метод определения является ли тип ссылкой: (В рамках возможной применимости)


template<class T>
class WarpType {
    typedef T OriginalType;
};

template <class T>
struct ReferenceTester {
    template <class TT>
        static TT&(* GetSpecialPointer2Function(WarpType<TT>) )(WarpType<TT>);
        static NO    GetSpecialPointer2Function(...);

    template <class TT> 
        static NO    Comparator( TT&(*)(WarpType<TT>) );    // ссылка на ссылку запрещена =>
        static YES    Comparator(...);                    // выберет этот вариант ...

        enum {value = sizeof(Comparator(GetSpecialPointer2Function(WarpType<T>()))) == sizeof(YES)};
        
    };


Поскольку стандарт я себе плохо представляю, то мне сложно оценить всю непригодность метода... А другой придумывать уже лень.

Так что, если что, давайте ваши предложения... Исправляйте!!!
Re[14]: sizeof(array) in template
От: Denn  
Дата: 21.02.03 18:27
Оценка:
Здравствуйте, Denn, Вы писали:

А так наверно, со стандартом совместимо!!!

template<class T>
class WarpType {
    typedef T OriginalType;
};

    template <class U>
        class ArrayTester
        {
            template<class T> 
                static T(* ReturnTModificator( WarpType<T> ) )(WarpType<T>);
                static YES    ReturnTModificator(...);   // Выберется эта версия для типов массивов.

            template<class T> 
                static CBPrivate::NO Comparator(  T(*)(WarpType<T>)  );
                static CBPrivate::YES Comparator(...);
            public:
                enum {
                    value = sizeof(Comparator(ReturnTModificator( WarpType<U>() )))
                        == sizeof(CBPrivate::YES)
                };
        };


Re[14]: sizeof(array) in template
От: Denn  
Дата: 06.03.03 13:06
Оценка:
Здравствуйте, Denn, Вы писали:

D>Предлагаю метод определения является ли тип ссылкой:

D>
D>
D>template<class T>
D>class WarpType {
D>    typedef T OriginalType;
D>};

D>template <class T>
D>struct ReferenceTester {
D>    template <class TT>
D>        static TT&(* GetSpecialPointer2Function(WarpType<TT>) )(WarpType<TT>);
D>        static NO    GetSpecialPointer2Function(...);

D>    template <class TT> 
D>        static NO    Comparator( TT&(*)(WarpType<TT>) );    // ссылка на ссылку запрещена =>
D>        static YES    Comparator(...);                    // выберет этот вариант ...

D>        enum {value = sizeof(Comparator(GetSpecialPointer2Function(WarpType<T>()))) == sizeof(YES)};
D>        
D>    };
D>


Жалко не видно активности по теме, а ведь она еще далека до полного решения...

На сколько я вижу, код вроде стандарту соответствует, и теоретически работает

НО!!! MSVC падает на ссылках на функции!

typedef double (&ntt)();   // ! ! !
cout << "DURA " << typeid( ReferenceTester<ntt>::GetSpecialPointer2Function( WarpType<ntt> () )   ).name() << endl;

Родив ссылку на ссылку в GetSpecialPointer2Function, MSVC не отбрасывает вариант, а падает с INTERNAL COMPILER ERROR..


Как он запарил.. Че делать то???
Re[15]: sizeof(array) in template
От: Denn  
Дата: 06.03.03 14:37
Оценка:
Здравствуйте, Denn, Вы писали:

D> НО!!! MSVC падает на ссылках на функции!


Хмм.. Ну, слегка поспешил... Падает, если включена Generate browse info...

Если отключить, то собирается и работает.
Re[16]: sizeof(array) in template
От: Denn  
Дата: 07.03.03 20:01
Оценка:
Next...

Функциональные типы: Поскольку у нас есть IsReference и IsArray которые одновременно принимают за свои — функциональные типы, казалось бы тривиальное решение считать те типы функциональными которые IsReference && IsArray... И для большинства случаев это действительно работает Особенно мощно можно протащиться от того, что это решение может распознать произвольный функциональный тип!!!

Однако серьезный подход подразумевает корректность на любом входе...
А мы можем инстанцировать шаблон типом Type[], который распознается и как массив и как ссылка одновременно. (Других таких типов я не знаю, подскажите, если знаете) Что приводит серьезной к проблеме...

Взглянем как реализована детекция функциональных типов в boost... Легко видеть, что эта реализация имеет явный изъян-исключение, она не компилируется на ссылках на функциональные типы, тем не менее, она правильно работает на Types[] (есть и не явный изъян, то что определяются функции лишь до некоторого конечного числа аргументов)
А все из-за не глубокомысленно ляпнутой строки кода:

    static T* t;


Итого: используя эти два подхода можно получить определение массива, ссылки и функции. Которое будет работать лучше (правильней), чем boost!!!

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

ЗЫЖ Рассуждения относятся к моим вариантам кода соответствующим стандарту (спасибо, Андрей ) и к варианту Андрея. Вариант определения ссылки Павла в его недавней статье, лично мне не нравится, из-за проблем с CV квалификаторами.
Re[2]: sizeof(array) in template
От: Sergeem Израиль  
Дата: 12.05.03 18:52
Оценка: 39 (3)
Здравствуйте, Gregory, Вы писали:

G>Всем спасибо, господа!

G>Собрав воедино все, что вы написали по данной теме, удалось получить работующий код(т):
...

Во, краткость — сестра таланта!
template <class T, int Size>
char (& lengthof(T (&)[Size]))[Size];

#define lengthof(a) sizeof(lengthof(a))

Это Rani Sharoni такой умный, а не я....
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.