Выбирается не та функция
От: Aera Беларусь  
Дата: 04.08.05 08:04
Оценка:
В 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'
}


Кто виноват и что можно сделать, чтобы заставить работать указанный код.
--
RedApe
Re: Выбирается не та функция
От: Glоbus Украина  
Дата: 04.08.05 08:13
Оценка:
Здравствуйте, 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() — отсюда и ошибка.
Удачи тебе, браток!
Re: Выбирается не та функция
От: Bell Россия  
Дата: 04.08.05 08:14
Оценка:
Здравствуйте, 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.
Любите книгу — источник знаний (с) М.Горький
Re: Выбирается не та функция
От: korzhik Россия  
Дата: 04.08.05 08:29
Оценка: 3 (2)
Здравствуйте, 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();
}


Вот только не уверен насчёт того будет ли это работать на шестёрке
Re[2]: Выбирается не та функция
От: MaximE Великобритания  
Дата: 04.08.05 09:31
Оценка: 4 (2)
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 Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[2]: Выбирается не та функция
От: Aera Беларусь  
Дата: 04.08.05 09:46
Оценка: 1 (1)
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
--
RedApe
Re[3]: Выбирается не та функция
От: korzhik Россия  
Дата: 04.08.05 09:53
Оценка: 1 (1)
Здравствуйте, 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.


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