VC6 & CV-квалификаторы
От: Кодт Россия  
Дата: 18.02.04 18:50
Оценка:
Вот блин, сходил за спичками... делал простенький синглетончик...

Комяу не нашёл проблем — а шестёрка нашла.

#include <iostream>
using namespace std;

template<class T>
struct Common
{
  int i;
  
  static Common self;
};

template<class T>
Common<T> Common<T>::self = { 0 };

template<class T>
Common<T>& common(const volatile T* v)
{
  return Common<T>::self;
}

class Test
{
public:
  void f() const
  {
    Common<Test> dummy = { 1 };
    dummy = common(this); // error!
    dummy = Common<Test>::self; // ok

    cout << common(this).i << endl;
  }
  void g()
  {
    common(this).i = 1;
  }
};

int main()
{
  Test t;
  t.g();
  t.f();
}

Результат VC6 заявил
e.cpp(27) : error C2679: binary '=' : no operator defined which takes a right-hand operand
of type 'struct Common<class Test>' (or there is no acceptable conversion)


Если мы уберём проблемную строку, и просто будем пользоваться common(this) и Common<Test>::self -- обнаружим, что у них разные адреса!

Оказывается, это попросту разные типы:
class Test
{
public:
  void f() const
  {
    cout << typeid(&common(this)).name() << endl;       // struct Common<class Test const > *
    cout << typeid(&Common<Test>::self).name() << endl; // struct Common<class Test > *
    //             |
    //             +---- чтобы избавиться от ссылочного типа
  }
};

main()
{
  Test test;
  const Test ctst;

  test.f();
  cout << typeid(&common(&test)).name() << endl; // struct Common<class Test > *
  cout << typeid(&common(&ctst)).name() << endl; // struct Common<class Test const > *
}


Засада притаилась вот где:
template<class T>
Common<T>& common(const volatile T* v)

стоит нам убрать volatile — и всё встаёт на место.

Оба квалификатора добавлены с единственной целью: не различать указатели на класс с и без этих квалификаторов.
То есть
Test t;

Test* p = &t;
const Test* pc = &t;
volatile Test* pv = &t;
const volatile Test* pvc = &t;




После такой находки я бы поостерёгся пользоваться библиотекой Loki, где этих volatile — как собак нерезанных, именно с целью ингибирования cv-квалификаторов.

ЗЫ.
Проверьте на VC7, плиз.
Перекуём баги на фичи!
Re: VC6 & CV-квалификаторы
От: Шахтер Интернет  
Дата: 18.02.04 23:55
Оценка:
Здравствуйте, Кодт, Вы писали:

Меняй студию.

/* main.cpp */ 

#include <iostream>
#include <typeinfo>

using namespace std;

/* struct Common<T> */ 

template <class T>
struct Common
 {
  int i;
  
  static Common self;
 };

template <class T>
Common<T> Common<T>::self={0};

template <class T>
Common<T> & common(const volatile T *)
 {
  return Common<T>::self;
 }
 
/* struct Test */  

struct Test 
 {
 };

/* main() */ 

int main()
 {
  Test t;

  Test *p=&t;
  const Test *pc=p;
  volatile Test *pv=p;
  const volatile Test *pvc=p;
 
  cout << typeid(&common(p)).name() << endl ;
  cout << typeid(&common(pc)).name() << endl ;
  cout << typeid(&common(pv)).name() << endl ;
  cout << typeid(&common(pvc)).name() << endl ;
 
  return 0;
 }


struct Common<struct Test> *
struct Common<struct Test> *
struct Common<struct Test> *
struct Common<struct Test> *
Press any key to continue

... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: VC6 & CV-квалификаторы
От: Кодт Россия  
Дата: 19.02.04 00:09
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Меняй студию.


Я подумать в эту сторону... Но у меня их две — VC6 и eVC4 (на базе всё той же VC6)...
... << RSDN@Home 1.1.2 stable >>
Перекуём баги на фичи!
Re[3]: VC6 & CV-квалификаторы
От: folk Россия  
Дата: 19.02.04 00:21
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Шахтер, Вы писали:


Ш>>Меняй студию.


К>Я подумать в эту сторону... Но у меня их две — VC6 и eVC4 (на базе всё той же VC6)...


Че думать — меняйся, пока Шахтер не передумал
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.