Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> template<T> or template<T*> Как частично, спец. в зав. от указатель или нет? 
:(
    Опции темы
np9mi7
  Дата 17.6.2005, 08:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



Добрый день.

Есть шаблон функтора:

Код

template<class T,int (T::*pfnCreateIntView)() const> struct __compare
{
    bool operator()(const T& utArg1,const T& utArg2) const throw()
    {
        return (utArg1.*pfnCreateIntView)() < (utArg2.*pfnCreateIntView)();
    }
};


Можно ли его частично специализировать в зависимости: T - указатель или нет? Если да, то как?

Это важно, потому как влияет на реализацию оператора ():

Код

return (utArg1->*pfnCreateIntView)() < (utArg2->*pfnCreateIntView)();


Заранее спасибо за помощь.


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
srd
Дата 17.6.2005, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Гм, а если попробовать обойтись без частичной специализации?
Код

template<class T,int (T::*pfnCreateIntView)() const> struct __compare    
{    
    bool operator()(const T& utArg1,const T& utArg2) const throw()    
    {    
        return (utArg1.*pfnCreateIntView)() < (utArg2.*pfnCreateIntView)();    
    }    

    bool operator()(const T* utArg1,const T* utArg2) const throw()    
    {    
        return (utArg1->*pfnCreateIntView)() < (utArg2->*pfnCreateIntView)();    
    }    
};




--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
Fantasist
Дата 17.6.2005, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: 4
Всего: 41



np9mi7 можно:


Код

template<class T,int (T::*pfnCreateIntView)() const> 
struct __compare<T*>
{
    bool operator()(const T& utArg1,const T& utArg2) const throw()
    {
        return (utArg1.*pfnCreateIntView)() < (utArg2.*pfnCreateIntView)();
    }
};


Добавлено @ 19:40
Только компилятор должен поддерживать частичную специализацию.
Если нет, то можно ее эмулировать, но это посложнее.




--------------------
Волны гасят ветер...
PM MAIL   Вверх
np9mi7
  Дата 17.6.2005, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 553
Регистрация: 17.8.2003
Где: Volgograd, Russia

Репутация: 5
Всего: 10



Код

template<class T,int (T::*pfnCreateIntView)() const> struct __compare    
{    
    bool operator()(const T& utArg1,const T& utArg2) const throw()    
    {    
        return (utArg1.*pfnCreateIntView)() < (utArg2.*pfnCreateIntView)();    
    }    
    bool operator()(const T* const& utArg1,const T* const& utArg2) const throw()    
    {    
        return (utArg1->*pfnCreateIntView)() < (utArg2->*pfnCreateIntView)();    
    }    
};


Да этот вариант вполне работает, ведь компилятор ищет подходящую подстановку и находит её smile

Но в таком методе есть проблема: теперь от
Код

template<class Arg1, class Arg2, class Result>
   struct binary_function {
      typedef Arg1 first_argument_type;
      typedef Arg2 second_argument_type;
      typedef Result result_type;
   };
не отнаследуешся smile

Поэтому и хотелось частично специализировать...

Fantasist, компилятор MSVC .net 2003:
Код

template<class T,int (T::*pfnCreateIntView)() const> struct __compare
{
    bool operator()(const T& utArg1,const T& utArg2) const throw()
    {
        return (utArg1.*pfnCreateIntView)() < (utArg2.*pfnCreateIntView)();
    }
};
template<class T,int (T::*pfnCreateIntView)() const> struct __compare<T*>
{
    bool operator()(const T& utArg1,const T& utArg2) const throw()
    {
        return (utArg1.*pfnCreateIntView)() < (utArg2.*pfnCreateIntView)();
    }
};


Цитата

d:\Proga\examples\template_functor\template_functor\template_functor.cpp(21): error C2953: '__compare' : template class has already been defined
d:\Proga\examples\template_functor\template_functor\template_functor.cpp(16): error C2976: '__compare' : too few template arguments


почемуто он так не хочет частично специализировать smile

Это сообщение отредактировал(а) np9mi7 - 17.6.2005, 21:08


--------------------
"Я точно знаю то, что ничего не знаю..." Сократ.
evolution project
PM MAIL WWW ICQ MSN   Вверх
bel_nikita
Дата 17.6.2005, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

Репутация: 21
Всего: 47



Попробуй так:
Код

template<class T,int (T::*pfnCreateIntView)() const> struct __compare
{
    bool operator()(const T& utArg1,const T& utArg2) const throw()
    {
        return (utArg1.*pfnCreateIntView)() < (utArg2.*pfnCreateIntView)();
    }
};
template<class T,int (T::*pfnCreateIntView)() const> struct __compare<T*>
{
    typedef T* PT; // <<<<<<<<<<<<<<<
    bool operator()(const PT& utArg1,const PT& utArg2) const throw()
    {
        return (utArg1.*pfnCreateIntView)() < (utArg2.*pfnCreateIntView)();
    }
};




--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Earnest
Дата 18.6.2005, 06:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Нет, так тоже не правильно: при специализации второй список должен содержать все аргументы.


Это сообщение отредактировал(а) Earnest - 18.6.2005, 07:16


--------------------
...
PM   Вверх
Earnest
Дата 18.6.2005, 07:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Нет, так тоже неправильно: список аргументов во вторых скобках должен быть полным. Формально, правильно так:

Код

template<class T,int (T::*pfnCreateIntView)() const> 
struct __compare
{
   bool operator()(const T& lhs,const T& rhs) const
   {
        return (lhs.*pfnCreateIntView)() < (rhs.*pfnCreateIntView)();
   }
};

template<class T,int (T::*pfnCreateIntView)() const> 
struct __compare <T*,pfnCreateIntView> 
{
   bool operator()(const T* lhs,const T* rhs) const
   {
       return (lhs->*pfnCreateIntView)() < (rhs->*pfnCreateIntView)();
   }
};


Это объявление само по себе компилируется, но дальше не помогает. В смысле, использовать не удается.

Код

struct Test
{
    int CreateView() const;
};

void foo()
{
    std::vector<Test> a;
    std::vector<Test*> b;
    
                // это компилируется
    std::sort(a.begin(),a.end(),__compare<Test,Test::CreateView>());
                // а это - нет
    std::sort(b.begin(),b.end(),__compare<Test*,Test::CreateView>());
    
}


Почему - непонятно...
А вообще, как задача-то стоит? Как предполагается этот шаблон применять?
Вывести тип шаблон, не указывая явно тип аргументов, не получится - это ведь не функция.

Зато если использовать boost:: bind, то можно написать так:

Код

using namespace boost;

std::sort(a.begin(),a.end(),bind(std::less<int>(),bind(Test::CreateView,_1),bind(Test::CreateView,_2)));

std::sort(b.begin(),b.end(),bind(std::less<int>(),bind(Test::CreateView,_1),bind(Test::CreateView,_2)));


И не надо никаких шаблонов...


--------------------
...
PM   Вверх
Fantasist
Дата 18.6.2005, 08:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: 4
Всего: 41



Цитата(Earnest @ 18.6.2005, 04:14)
Нет, так тоже неправильно: список аргументов во вторых скобках должен быть полным.


Да, конечно, список аргументов должен быть полным. И тип аргументов у оператора() тоже должен быть изменен соотвественно. Спасибо за поправку.


Цитата(Earnest @ 18.6.2005, 04:14)
         
    // а это - нет
    std::sort(b.begin(),b.end(),__compare<Test*,Test::CreateView>());


А как ругается-то хоть?


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Earnest
Дата 18.6.2005, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Вот (MSVC.NET 2003):

Цитата
Src\Templates.cpp(39) : error C2955: '__compare' : use of class template requires template argument list
        Src\Templates.cpp(16) : see declaration of '__compare'
Src\Templates.cpp(39) : error C2780: 'void stlp_std::sort(_RandomAccessIter,_RandomAccessIter)' : expects 2 arguments - 3 provided
        C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\STL\inc\stl\_algo.h(426) : see declaration of 'stlp_std::sort'
Src\Templates.cpp(39) : error C3861: '__compare': identifier not found, even with argument-dependent lookup


Я так понимаю, 2-я и 3-я ошибки уже производные. А 1-я - не нравится ему несоответствие объявления шаблона template <class T, int (T::*pfn...() const> и применения __compare<Test*,Test::CreateView>...



--------------------
...
PM   Вверх
srd
Дата 18.6.2005, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Вот так работает в MSVC++ 2003 .NET
Код

template<class T, class TT, int (TT::*pfnCreateIntView)() const> struct __compare
{
    bool operator()(const T& utArg1,const T& utArg2) const throw()
    {
        return (utArg1.*pfnCreateIntView)() < (utArg2.*pfnCreateIntView)();
    }
};

template<class T, class TT, int (TT::*pfnCreateIntView)() const> struct __compare<T*, TT, pfnCreateIntView>
{
    bool operator()(const T* utArg1, const T* utArg2) const throw()
    {
        return (utArg1->*pfnCreateIntView)() < (utArg2->*pfnCreateIntView)();
    }
};

class A
{
public:
    int func() const {return 0;}
};

int main(void)
{
    A a1, a2;
    __compare<A, A, A::func> c1;
    c1(a1, a2);

    A *p1 = &a1, *p2 = &a2;
    __compare<A*, A, A::func> c2;
    c2(p1, p2);

    return 0;
}

Вот как бы от третьего аргумента избавиться smile


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
Chaos A.D.
Дата 20.6.2005, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



А почему бы не передавать указатель на функцию-член в качестве параметра конструктору функтора? Как мне кажется, это решит все проблемы.
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
Earnest
Дата 20.6.2005, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



И то правда, Chaos.



--------------------
...
PM   Вверх
Chaos A.D.
Дата 20.6.2005, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Вот пример, как я заюзал такую идею :

Код

class Foo
{
    private :
        int x;
    public :
        Foo( int xx = 8 ) : x(xx) {};
        int GetInt( void ) const { return x; }
};

template<class T>
class compare
{
        int (T::*ptr) (void) const;
    public :
        compare( int (T::*p)(void) const ) : ptr(p) {};
        bool operator()( const T& utArg1, const T& utArg2 ) const throw()
        {
            return (utArg1.*ptr)() < (utArg2.*ptr)();
        }
};

template <class T>
class compare<T*>
{
        int (T::*ptr) (void) const;
    public :
        compare( int (T::*p)( void ) const ) : ptr(p) {};
        bool operator()( const T* utArg1, const T* utArg2 ) const throw()
        {
            return (utArg1->*ptr)() < (utArg2->*ptr)();
        }
};

template <class T>
struct Print
{
        ostream &out;
    public :
        Print( ostream &to ) : out(to) {}
        bool operator() ( const T &f ) const
        { out << "Foo::x == " << f.GetInt() << endl; }
};

template <class T>
struct Print<T*>
{
        ostream &out;
    public :
        Print( ostream &to ) : out(to) {}
        bool operator() ( const T *f ) const
        { out << "Foo::x == " << f->GetInt() << endl; }
};

int main()
{
         // В куче
    vector<Foo*> vec;
    vec.push_back(new Foo(3));
    vec.push_back(new Foo(1));
    vec.push_back(new Foo(8));
    vec.push_back(new Foo(2));
    vec.push_back(new Foo(43));
    vec.push_back(new Foo(32));
    sort( vec.begin(), vec.end(), compare<Foo*>(&Foo::GetInt) );
    for_each( vec.begin(), vec.end(), Print<Foo*>(cout) );

         // На стеке
    vector<Foo> vec2;
    vec2.push_back(3);
    vec2.push_back(1);
    vec2.push_back(8);
    vec2.push_back(2);
    vec2.push_back(43);
    vec2.push_back(32);
    sort( vec2.begin(), vec2.end(), compare<Foo>(&Foo::GetInt) );
    for_each( vec2.begin(), vec2.end(), Print<Foo>(cout) );
};


--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1534 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.