Второй делитанский вопрос По специализации шаблонов.. в избранное  новое горячее всё    подписка   модер. 
От: alexsy 
Дата: 28.05.08 07:41
Выяснено что можно специализировать не весь клас а тока члены, члены функции и статические члены..

вот мой класс ( написан чисто для тестирования этого вопроса.. ) реализацию приводить не буду .. чисто то что интересует.


/**/
template< typename Type, typename Sequence = std::vector< Type > >
class CSortedArray;
/**/
template< typename Type, typename Sequence >
class CSortedArray{
public:
    typedef typename Sequence::value_type value_type;
    typedef typename Sequence::reference reference;
    typedef typename Sequence::const_reference const_reference;
    typedef typename Sequence::size_type size_type;
    typedef typename Sequence::const_iterator const_iterator;
    typedef Sequence container_type;
    Sequence pvArray;
private:
    typedef typename Sequence::iterator iterator;
    typename CSortedArray< Type, Sequence >::iterator
            find_position( const value_type& f_Element );
    template< typename Iterator >
    void copy_from( Iterator f_Begin, Iterator f_End ){ ... }
public:
    
    explicit CSortedArray( const Sequence& f_Array = Sequence() );
    ~CSortedArray(){};
#if 0 // used by default
    CSortedArray( CSortedArray< Type > const& f_SortedArray );
    CSortedArray< Type >& operator=( CSortedArray< Type > const& f_SortedArray );
#endif
    typename CSortedArray< Type, Sequence >::const_iterator
            insert( const typename CSortedArray< Type, Sequence >::value_type&
                    f_Element );
    size_type size() const;
    bool empty() const;
/*
    const_reference operator[]( size_type ) const{};
*/
    const_iterator begin() const;
    const_iterator end() const;
};
// Далее реализация общей функции
template< typename Type, typename Sequence >
typename CSortedArray< Type, Sequence >::iterator
CSortedArray< Type, Sequence >::find_position( const value_type& f_Element ) {

    typedef typename iterator::difference_type distance;
    iterator begin( pvArray.begin() );
    iterator end( pvArray.end() );
    distance dist( std::distance( begin, end ) );
    while( dist > 0 ){
        dist >>= 1;
        iterator middle( begin );
        std::advance( middle, dist );
        if( middle == pvArray.end() )
            return pvArray.end();
        if( f_Element < *middle )
            end = middle;
        else if( f_Element > *middle )
            begin = middle + 1;
        else
            return middle;
        }
    return end;
}
// Далее реализация специалезированной функции для указателей на cstring
template<>
CSortedArray< char*, std::vector< char* > >::iterator
CSortedArray< char*, std::vector< char* > >::find_position(
        const value_type& f_Element ) \{

    typedef iterator::difference_type distance;

    int test;
    iterator begin( pvArray.begin() );
    iterator end( pvArray.end() );
    distance dist( std::distance( begin, end ) );
    while( dist > 0 ){
        dist >>= 1;
        iterator middle( begin );
        std::advance( middle, dist );
        if( middle == pvArray.end() )
            return pvArray.end();
        test = std::strcmp( f_Element, *middle );
        if( test < 0 )
            end = middle;
        else if( test > 0 )
            begin = middle + 1;
        else
            return middle;
        }
    return end;
}

И так вопрос из объявления шаблона (template< typename Type, typename Sequence = std::vector< Type > > class CSortedArray видно что в качестве последовательности можно указать несколько контейнеров.. по умолчению std::vector, А в специализированной функции указан только std::vector, вот как переписать специалезированную функцию, так чтобы небыло зависимости от контейнера..? или это не возможно ? И надо писать специализацию для std::deque непример
Re: Второй делитанский вопрос По специализации шаблонов.. в избранное  новое    модер. 
От: Bell 
Дата: 28.05.08 09:29
Здравствуйте, alexsy, Вы писали:

A>И так вопрос из объявления шаблона (template< typename Type, typename Sequence = std::vector< Type > > class CSortedArray видно что в качестве последовательности можно указать несколько контейнеров.. по умолчению std::vector, А в специализированной функции указан только std::vector, вот как переписать специалезированную функцию, так чтобы небыло зависимости от контейнера..? или это не возможно ? И надо писать специализацию для std::deque непример


В данном случае специализация не поможет, т.к. как ты и сам сказал, в специализированной функции нужно точно указывать тип контейнера (вернее, если есть желание писать специализацию для каждого контейнера — то вперед ). Однако здесь можно обойтись перегрузкой:

template< typename Type, typename Sequence >
class CSortedArray{
public:
    typedef typename Sequence::value_type value_type;
...
private:
    typedef typename Sequence::iterator iterator;
    iterator find_position( const value_type& f_Element );
    iterator find_position( char* f_Element );
...



template< typename Type, typename Sequence >
typename CSortedArray< Type, Sequence >::iterator
CSortedArray< Type, Sequence >::find_position( const value_type& f_Element )
{
//Общая реализация
}


template< typename Type, typename Sequence >
typename CSortedArray< Type, Sequence >::iterator
CSortedArray< Type, Sequence >::find_position( char* f_Element )
{
//Реализация для char*
}


ЗЫ
Контейнеро-независимый код таит в себе много опасностей — обсуждалось это не раз, посмотри в поиске.

ЗЗЫ
Запись
typedef iterator::difference_type distance

в общем случае некорректна, т.к. у того же вектора итератор может быть обычным указателем. Правильнее вот так:
typedef typename std::iterator_traits<iterator>::difference_type distance;


ЗЗЗЫ
Для бинарного поиска можно использовать std::lower_bound
Любите книгу — источник знаний (с) М.Горький
Re[2]: Второй делитанский вопрос По специализации шаблонов.. в избранное  новое    модер. 
От: alexsy 
Дата: 28.05.08 09:34
Здравствуйте, Bell, Вы писали:

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


A>>И так вопрос из объявления шаблона (template< typename Type, typename Sequence = std::vector< Type > > class CSortedArray видно что в качестве последовательности можно указать несколько контейнеров.. по умолчению std::vector, А в специализированной функции указан только std::vector, вот как переписать специалезированную функцию, так чтобы небыло зависимости от контейнера..? или это не возможно ? И надо писать специализацию для std::deque непример


B>В данном случае специализация не поможет, т.к. как ты и сам сказал, в специализированной функции нужно точно указывать тип контейнера (вернее, если есть желание писать специализацию для каждого контейнера — то вперед ). Однако здесь можно обойтись перегрузкой:


B>
B>template< typename Type, typename Sequence >
B>class CSortedArray{
B>public:
B>    typedef typename Sequence::value_type value_type;
B>...
B>private:
B>    typedef typename Sequence::iterator iterator;
B>    iterator find_position( const value_type& f_Element );
B>    iterator find_position( char* f_Element );
B>...
B>



B>
B>template< typename Type, typename Sequence >
B>typename CSortedArray< Type, Sequence >::iterator
B>CSortedArray< Type, Sequence >::find_position( const value_type& f_Element )
B>{
B>//Общая реализация
B>}


B>template< typename Type, typename Sequence >
B>typename CSortedArray< Type, Sequence >::iterator
B>CSortedArray< Type, Sequence >::find_position( char* f_Element )
B>{
B>//Реализация для char*
B>}
B>


B>ЗЫ

B>Контейнеро-независимый код таит в себе много опасностей — обсуждалось это не раз, посмотри в поиске.
Это поищем...

B>ЗЗЫ

B>Запись
B>
B>typedef iterator::difference_type distance
B>

B>в общем случае некорректна, т.к. у того же вектора итератор может быть обычным указателем. Правильнее вот так:
B>
B>typedef typename std::iterator_traits<iterator>::difference_type distance;
B>

Учту..

B>ЗЗЗЫ

B>Для бинарного поиска можно использовать std::lower_bound
Да писалось не ради пробукта а ради практики ..
Re[2]: Второй делитанский вопрос По специализации шаблонов.. в избранное  новое    модер. 
От: Аноним 332 
Дата: 28.05.08 14:38
Здравствуйте, Bell, Вы писали:

B>template< typename Type, typename Sequence >

B>typename CSortedArray< Type, Sequence >::iterator
B>CSortedArray< Type, Sequence >::find_position( char* f_Element )
B>{
B>//Реализация для char*
B>}
B>[/ccode]

не удаётся компиляция если применено явное инстанцирование класса для типа int

template class CSortedArray< int >;

template< typename Type, typename Sequence >
typename CSortedArray< Type, Sequence >::iterator
CSortedArray< Type, Sequence >::find_position( const char* f_Element ){

    typedef typename std::iterator_traits< iterator >::difference_type distance;

    int test;
    iterator begin( pvArray.begin() );
    iterator end( pvArray.end() );
    distance dist( std::distance( begin, end ) );
    while( dist > 0 ){
        dist >>= 1;
        iterator middle( begin );
        std::advance( middle, dist );
        if( middle == pvArray.end() )
            return pvArray.end();
        test = std::strcmp( f_Element, *middle );
        if( test < 0 )
            end = middle;
        else if( test > 0 )
            begin = middle + 1;
        else
            return middle;
        }
    return end;
}

../src/test_template_SortedArray2.cpp:111: error: invalid conversion from ‘int’ to ‘const char*’
../src/test_template_SortedArray2.cpp:111: error: initializing argument 2 of ‘int strcmp(const char*, const char*)’
типа хочет она фукнцию с явным параметром за место шаблонного .. Без Яаного инстанцирования работает..
Re: Второй делитанский вопрос По специализации шаблонов.. в избранное  новое    модер. 
От: Eugene Kilachkoff 
Дата: 28.05.08 15:13
Здравствуйте, alexsy, Вы писали:

A>
A>/**/
A>template< typename Type, typename Sequence = std::vector< Type > >
A>class CSortedArray;


A>как переписать специалезированную функцию, так чтобы небыло зависимости от контейнера..? или это не возможно ? И надо писать специализацию для std::deque непример


Я бы вообще ушел от специализированной функции, ровно также как делают в STL:
template< typename Type, typename Sequence = std::vector< Type >, typename Compare = std::less<Type> >
// ....
    test = Compare(f_Element, *middle);


Слегка неудобно -- придется в местах инстанцирования прописывать какой-нибудь less_pchar типа
struct less_pchar
{
   // ...
   bool operator()(char const *lhs, char const *rhs) const
   {
      return strcmp(lhs,rhs) < 0;
   }
}


ps. strcmp можно еще заменить на std::char_traits::compare или как ее там....