В VC6.0 имеем следующую ситуацию
struct base
{
virtual ~base();
virtual void ok();
};
struct derived : public base
{
};
template<class T> void foobar(T *self)
{
self->damn();
}
void foobar(base* self)
{
self->ok();
}
void test()
{
derived *f=0;
foobar( f ); // error C2039: 'damn' : is not a member of 'derived'
}
Кто виноват и что можно сделать, чтобы заставить работать указанный код.
Здравствуйте, Aera, Вы писали:
A>В VC6.0 имеем следующую ситуацию
A>A>struct base
A>{
A> virtual ~base();
A> virtual void ok();
A>};
A>struct derived : public base
A>{
A>};
A>template<class T> void foobar(T *self)
A>{
self->>damn();
A>}
A>void foobar(base* self)
A>{
self->>ok();
A>}
A>void test()
A>{
A> derived *f=0;
A> foobar( f ); // error C2039: 'damn' : is not a member of 'derived'
A>}
A>
A>Кто виноват и что можно сделать, чтобы заставить работать указанный код.
Могу ошибаться, но как мне кажется в данном случае будет вызвана более подходящая функция, полученная при инстанцировании шаблона с параметром T = derived; но derived не имеет метода damn() — отсюда и ошибка.
Здравствуйте, Aera, Вы писали:
A>В VC6.0 имеем следующую ситуацию
A>A>struct base
A>{
A> virtual ~base();
A> virtual void ok();
A>};
A>struct derived : public base
A>{
A>};
A>template<class T> void foobar(T *self)
A>{
self->>damn();
A>}
A>void foobar(base* self)
A>{
self->>ok();
A>}
A>void test()
A>{
A> derived *f=0;
A> foobar( f ); // error C2039: 'damn' : is not a member of 'derived'
A>}
A>
A>Кто виноват и что можно сделать, чтобы заставить работать указанный код.
При прочих равных условиях обычная функция имеет преимущество перед шаблоном функции. В данном же случае из шаблона получаем функцию
void foobar(derived *self);
которая, естественно лучше подходит, чем обычная
void foobar(base* self);
Как бороться:
1. При вызове foobar явно указывать тип base:
void test()
{
derived *f=0;
foobar( (base*)f );
}
2.
Перегрузить foobar для аргумента типа derived* .
3.
Написать шаблон-диспетчер, в котором с помощью приемов метапрограммирования определять, является ли Т производным от base, и если да — то вызывать нешаблонную foobar, иначе — шаблонную foobar.
Здравствуйте, Aera, Вы писали:
A>В VC6.0 имеем следующую ситуацию
[]
A>Кто виноват и что можно сделать, чтобы заставить работать указанный код.
Виноват C++. Можно переписать шаблонный foobar следуюшим способом:
#include "boost/utility/enable_if.hpp"
#include "boost/type_traits/is_base_and_derived.hpp"
template<class T>
typename boost::disable_if<boost::is_base_and_derived<base,T> >::type foobar(T *self)
{
self->damn();
}
Вот только не уверен насчёт того будет ли это работать на шестёрке
korzhik wrote:
> Здравствуйте, Aera, Вы писали:
>
> A>В VC6.0 имеем следующую ситуацию
>
> []
>
> A>Кто виноват и что можно сделать, чтобы заставить работать указанный код.
>
> Виноват C++. Можно переписать шаблонный foobar следуюшим способом:
> > #include "boost/utility/enable_if.hpp"
> #include "boost/type_traits/is_base_and_derived.hpp"
>
> template<class T>
> typename boost::disable_if<boost::is_base_and_derived<base,T> >::type foobar(T *self)
> {
> self->damn();
> }
>
>
> Вот только не уверен насчёт того будет ли это работать на шестёрке
И на шахе можно заставить:
template<class T>
void foobar(T* self, typename if_<is_base_and_derived<base,T>, int, int&>::type* = 0)
[boost] Some SFINAE for vc6
--
Maxim YegorushkinPosted via RSDN NNTP Server 1.9
K>Вот только не уверен насчёт того будет ли это работать на шестёрке
На шестерке сделал так:
#include <boost\type_traits\is_base_and_derived.hpp>
struct base
{
virtual ~base();
virtual void ok();
};
struct derived : public base
{
};
template<bool>
struct foobar_selector
{
template<class T>
static void foobar(T* self)
{
self->damn();
}
};
template<>
struct foobar_selector<1>
{
static void foobar(base* self)
{
self->ok();
}
};
template<class T>
void foobar(T* self)
{
foobar_selector<boost::is_base_and_derived<base, T>::value>::foobar(self);
}
void test()
{
derived *f=0;
foobar( f );
}
--
Aera
Здравствуйте, Aera, Вы писали:
K>>Вот только не уверен насчёт того будет ли это работать на шестёрке
A>На шестерке сделал так:
A>#include <boost\type_traits\is_base_and_derived.hpp>
отлично. Только если педантично относиться к языку, то использование "\" в инклудах ведёт к неопределённому поведению:
2.8/2
If either of the characters ’ or \, or either of the character sequences /* or // appears in a q-char-sequence
or a h-char-sequence, or the character " appears in a h-char-sequence, the behavior is undefined.
--------------------
Thus, sequences of characters that resemble escape sequences cause undefined behavior.
В инклудах всегда используй "/"