Вот блин, сходил за спичками... делал простенький синглетончик...
Комяу не нашёл проблем — а шестёрка нашла.
#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, плиз.
Здравствуйте, Кодт, Вы писали:
Меняй студию.
/* 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 >>
Здравствуйте, Шахтер, Вы писали:
Ш>Меняй студию.
Я подумать в эту сторону... Но у меня их две — VC6 и eVC4 (на базе всё той же VC6)...
... << RSDN@Home 1.1.2 stable >>
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Шахтер, Вы писали:
Ш>>Меняй студию.
К>Я подумать в эту сторону... Но у меня их две — VC6 и eVC4 (на базе всё той же VC6)...
Че думать — меняйся, пока Шахтер не передумал
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн