Маленький и очень скромный шаблон:
template< class Delegate, class Arg, class Result >
class closure_t :
public std::unary_function< Arg, Result >
{
private:
Delegate& _d;
Result (Delegate::*_f)(Arg);
public:
explicit closure_t(Delegate& d, Result (Delegate::*f)(Arg)) :
_d(d), _f(f)
{}
Result operator()(Arg x) const
{
return (_d.*_f)(x);
}
};
... со вспомогательной функцией:
template< class Delegate, class Arg, class Result >
closure_t< Delegate, Arg, Result > closure(Delegate& d, Result (Delegate::*f)(Arg))
{
return closure_t< Delegate, Arg, Result >(d, f);
}
При попытке использования при Result = void, компилятор
(MSVC++ 6.0) ругается на
return в
closure_t::
operator()().
В связи с этим,
Вопрос 1: Он правильно ругается? Ведь (
_d.
_f)(
x) имеет тип
void, и, как мне раньше казалось, такая конструкция допустима. И как тогда работают
std::
mem_fun_t и прочие, если тип адаптируемой функции
void?
Далее, пытаясь обойти сие, тщусь написать специализацию:
template< class Delegate, class Arg >
class closure_t< Delegate, Arg, void > :
public std::unary_function< Arg, void >
{
private:
Delegate& _d;
void (Delegate::*_f)(Arg);
public:
explicit closure_t(Delegate& d, void (Delegate::*f)(Arg)) :
_d(d), _f(f)
{}
void operator()(Arg x) const
{
(_d.*_f)(x);
}
};
Компилятор мне на это отвечает:
error C2989: 'closure_t<Delegate,Arg,void>' : template class has already been defined as a non-template class
error C2988: unrecognizable template declaration/definition
Вопрос 2: Что не так в этой специализации?
PS: К сожалению, образцов типа boost под рукою нет.
Здравствуйте achp, Вы писали:
DG>>Ты напоролся сразу на две ошибке в компиляторе VC6.
DG>>1. VC6 не поддерживает тип void в полной мере
DG>>2. VC6 не поддерживает частичную специализацию шаблонов.
A>Спасибо на добром слове.
A>Так что же делать?
Пишется, что-то такое:
template< class Delegate, class Arg, class Result>
class _closure_base:
public std::unary_function< Arg, Result >
{
private:
Delegate& _d;
Result (Delegate::*_f)(Arg);
public:
explicit closure_t(Delegate& d, Result (Delegate::*f)(Arg)) :
_d(d), _f(f)
{}
};
template< class Delegate, class Arg, class Base>
class _closure_t:
public Base
{
public:
template<class Result>
class TT
{
Result operator()(Arg x) const
{
(_d.*_f)(x);
}
}
template<>
class TT<void>
{
void operator()(Arg x) const
{
(_d.*_f)(x);
}
}
};
template< class Delegate, class Arg, class Result >
class closure_t : public _closure_t<Delegate, Arg, _closure_base<Deletegate, Arg, Result> >::TT<Result>
{
};
Здравствуйте DarkGray, Вы писали:
Вернее, так:
template< class Delegate, class Arg, class Base>
class _closure_t
{
public:
template<class Result>
class TT:
public Base
{
Result operator()(Arg x) const
{
(_d.*_f)(x);
}
}
template<>
class TT<void>
{
void operator()(Arg x) const
{
(_d.*_f)(x);
}
}
};
Здравствуйте achp, Вы писали:
DG>>Ты напоролся сразу на две ошибке в компиляторе VC6.
DG>>1. VC6 не поддерживает тип void в полной мере
DG>>2. VC6 не поддерживает частичную специализацию шаблонов.
A>Спасибо на добром слове.
A>Так что же делать?
Так же применяется такая техника:
template<class T, class Arg, class Result>
struct Injection
{
template<class TResult>
struct TT0
{
Result operator()(Arg x) const
{
const T * t = static_cast<const T*>(this);
return (t->_d.*t->_f)(x);
}
};
template<>
struct TT0<void>
{
Result operator()(Arg x) const
{
const T * t = static_cast<const T*>(this);
(t->_d.*t->_f)(x);
}
};
typedef TT0<Result> TT;
};
template< class Delegate, class Arg, class Result >
class closure_t :
public std::unary_function< Arg, Result >,
public Injection<closure_t, Arg, Result>::TT
{
friend Injection<closure_t, Arg, Result>::TT;
private:
Delegate& _d;
Result (Delegate::*_f)(Arg);
public:
explicit closure_t(Delegate& d, Result (Delegate::*f)(Arg)) :
_d(d), _f(f)
{}
};
Здравствуйте achp, Вы писали:
DG>>Ты напоролся сразу на две ошибке в компиляторе VC6.
DG>>1. VC6 не поддерживает тип void в полной мере
DG>>2. VC6 не поддерживает частичную специализацию шаблонов.
A>Спасибо на добром слове.
A>Так что же делать?
У меня была похожая проблема, вот результат:
Адаптер обобщенного указателя на функцию-член классаАвтор(ы): Михаил Гусаров aka MAG
Рассуждения на тему обобщения некоторых конструкций STL и неполной совместимости компиляторов со стандартом C++
Здравствуйте DarkGray, Вы писали:
(...)
DG>template< class Delegate, class Arg, class Result >
DG>class closure_t : public _closure_t<Delegate, Arg, _closure_base<Deletegate, Arg, Result> >::template TT<Result>
DG>{
DG>};
В данном случае необходимо добавлять ключевое слово template, как указано в коде.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен