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, плиз.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.