Dmitry Leonov (leonov) wrote,
Dmitry Leonov
leonov

классвьюшнопобедное

При разборе косяков с ClassView в 2010-й студии было сразу понятно, что предпосылки проблемы восходят к тем уже далеким временам, когда один здоровый монолитный проект был разнесен по десятку dll. Первый подход был кривоват, полезли перекрестные ссылки подпроектов, которые через некоторое время пришлось разрулить железной рукой, при этом поперли кросс-ссылки инклюдов, которые разруливались в основном через активное использование forward-описаний классов (что, конечно, подпорки, но гораздо проще и быстрее долгого выстраивания правильного порядка инклюдов - опять же, не всегда достижимого).

В сочетании же с пространствами имен простое forward-описание приходится превращать в более громоздкие конструкции. Т.е., если в MyClass1 используется указатель на MyClass2, а живут они в разных пространствах имен, выглядеть это будет так:
namespace NS2
{
	class MyClass2;
}

namespace NS1
{
	class MyClass1
	{
		//...
		MyClass2* m_pXXX;
	};
}

Кроме того, в описании классов/функций из dll активно использовался вполне традиционный подход с выносом __declspec(dllexport/dllimport) в макросы, чтоб убрать поддержку двух наборов хедеров:
#ifdef MYDLLIMP
#define MYDLLEXP __declspec(dllexport)
#else
#define MYDLLEXP __declspec(dllimport)
#endif

После чего можно использовать это как
class MYDLLEXP MyClass
{
	//...
};

MYDLLIMP определялся только в проекте, где класс нужно было экспортировать, так что в реализации класс оказывался с dllexport, а в пользовательских проектах с dllimport.

Именно эти две вещи и сломали ClassView. Крышеснос с непопаданием в место с описанием случился от MYDLLEXP - ну не врубался новый IntelliSense в эти макросы между ключевым словом class и именем класса. Пришлось чуть подправить:
#ifdef MYDLLIMP
#define MYDLLEXP dllexport
#else
#define MYDLLEXP dllimport
#endif

class __declspec(MYDLLEXP) MyClass
{
	//...
};

Теперь все стало лучше, __declspec все-таки воспринимался как валидное ключевое слово, а что там внутри него, ClassView, к счастью, не волновало.

Ну а дубли в дереве возникли от сочетания forward-описаний с пространствами имен - каждое такое описание добавляло лишнюю строчку в дерево классов. Причем дубль возникал даже при описании дружественного класса из того же пространства имен:
namespace NS1
{
	class MyClass1
	{
		friend class MyClass3;
	};
}

Причина была понятна сразу, на устранение ушло несколько месяцев неспешных поисков (поскольку жить это особо не мешает, лишь тревожит чувство прекрасного).

Сначала искал подходящие настройки, потом подходящие прагмы, остановился же в итоге на следующем варианте, за который даже немного стыдно:
//stdafx.h
#ifndef __class
#define __class class
#define __struct struct
#endif

//myclass1.h
namespace NS2
{
	__class MyClass2;
}

namespace NS1
{
	class MyClass1
	{
		friend __class MyClass3;
		//...
		MyClass2* m_pXXX;
	};
}


Поскольку еще из опыта с __declspec стало понятно, что у ClassView особые отношения с макросами, был применен тот же подход, но уже в мирных целях, и этот грязный хак вполне прокатил - компилятору пофиг, в дереве чисто.

Tags: программизм, софт
Subscribe

  • яблочнопереключальное

    Продолжая обживаться на маке, не перестаю удивляться либо отсутствию, либо совершенно альтернативной логике реализации самых элементарных и привычных…

  • яблочноденежное

    Странное какое-то ценообразование на Маках. Один и тот же Elmedia Player в AppStore за PRO-версию хочет 1150 рублей, и ставить потом можно на все…

  • ГПБ vs TV

    Газпромбанк на днях обновил своё приложение, после чего словил кучу единиц в AppStore и Google Play за попытку принудить к удалению TV, поскольку «с…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

  • 0 comments