Visual Studio 2010: Not so nice improvements in TR1

Just moments after installing VS 2010 I found very nasty bug in its implementation of TR1 libraries:

            typedef struct sTestStruct
            {
                char* pName;
                char* pOtherName;
                sTestStruct* pNext;
            } sTestStruct;

            sTestStruct Struct1 = {"blah", "mlah", 0};

            char* pChar = bind(&sTestStruct::pName, _1)(&Struct1);            // Compiler is happy here

            bind(_stricmp, "blah", bind(&sTestStruct::pName, _1))(&Struct1);  // bang happens here

The error message is simply astonishing:

\microsoft visual studio 10.0\vc\include\functional(447): error C2440: ‘return’ : cannot convert from ‘char *’ to ‘char *&’

What is interesting, should I switch C++ toolset to version 9.0 (essentially switching back to VS 2008), the problem went away.

If I could I would suggest that something went horribly wrong when MS were working on rvalues (or were they lvalues?) references business, but there is simply no point guessing around. I just wonder how long will it take MS to fix the problem. Obviously, problems like this could mean that this new version of VS 2010 is not ready to be used in production yet.

Also, reporting bugs to MS has always been not so easy quest.

Кто о чем, а я о работе

M$ заботливо обеспечили C++ программистов годовым запасом грабель. Точнее, даже граблей – таких же кривых, как само это слово.

Сегодня компилятор мне в красках рассказывал, куда мне нужно было пройти.

Подробности позже телеграфом тчк.

Технологии – вперде! Redux (c)

Совсем забыл рассказать.

Как я уже упоминал, недавно оказалось, что C#, .NET и все, что с ними связано, я знаю довольно неплохо, to my surprise. Потом оказалось, что и Питон тоже знаю, но дело не в этом.

На прошлой неделе получил от всей из себя managed программы на 3.5 фреймворке вполне такой unmanaged Access Violation во всю морду. Мастерство, как говорится, не пропьешь.

Довольный собой, ушел домой. А что? Там же безопасный код и сборщик мусора, а моя хата с краю!

Студия 2010: дневник мыши, поедающей кактус

На вкус кактус пока ничего. За прошедшие три дня студия упала три раза и два раза зависла.

Что заметно:

  • Переработали меню проекта “добавить новую хрень”.  Выглядит ново, почти вебдванольно. Эргономика, правда, не изменилась.
  • Кажется, переписали Intelli(non)Sense. Как и обещали. Работает заметно быстрее и менее косячно. Впрочем, проект у нас пока в коротких штанишках, посмотрим, что будет дальше
  • IntelliSense точно если не переписали, то сурово ковыряли. По крайней мере, в предыдущих версиях она могла ставить Студию в разные позы в случае использования C++/Cli. Типичный пример – при использовании MSTest для тестирования C++ кода Студия начинала уходить в нирвану при сколько-нибудь приличном количестве тестов в проекте. В новой версии IntelliSense просто заявляет, что для C++/Cli оно работать не будет. И, что характерно, не работает.
  • MSTest теперь по умолчанию хранит результаты лишь для 25 запусков. Я, в принципе, вообще не понимаю всей этой затеи с хранениями результатов юнит-тестов. С моей точки зрения, тесты либо прошли, либо нет. Если тесты не прошли, билд не проходит тоже. End of story. В любом случае теперь, кажется, студия перестанет захламлять диск историей тестов, которая все равно никому не нужна.
  • Хост-процесс для тестов ведет себя странно. Периодически забывает завершиться, ввиду чего пересборка DLL с тестом обламывается. Подобного заскока за прежними версиями замечено не было.
  • Отладчик при работе в Mixed mode (тот самый случай тестирования С++ кода в MSTest) ведет себя неортодоксально. Норовит подвиснуть почем зря.
  • Зачем-то сломали поведение “Project dependencies”. Теперь, чтобы подсунуть линкеру другую статическую либу из этого же солюшена, нужно проект с библиотекой добавить в рефересы проекта. Совсем как в C# проектах. Немного неожидано. Зависимости проекта оставлены лишь для определения порядка сборки.

VS 2010: полет нормальный

Все идет четко по плану

DEP

За будущее разработки ПО я совершенно спокоен!

Технологический прорыв

Устанавливаю сегодня Visual Studio 2010. Прогресс заметен – процесс установки идет уже три часа, за которые компьютер перезагружался четыре раза.

Думаю, наконец-то программы начнут писаться сами.

Use boost to implement inter-class callbacks or delegates

In the software development, the pattern when one object has send a message to another object, where the object that has to be called is given to the first class somehow (usually in constructor), is quite common. In C#, the delegates serve exactly this purpose, but in C++ it is a different story.

The most common way of implementing the class-to-class callback in C++ is to define an interface, which the class that receives the event must implement:

class IInterface
{
public:
virtual void CallbackMethod() = 0;
}

class MyClass:
public IInterface
{
public:
virtual void CallbackMethod()
{
// do something useful
}

class Publisher
{
private:
IInterface* m_pCallee;
public:
Publisher(IInterface* pCallee):
m_pCallee(pCallee)
{
}

private:
void SomeMethod()
{
m_pCallee->CallbackMethod();
}
}
}

It isn’t exactly rocket science, but this method has some downsides, and some of them are quite nasty and not obvious at all. Those are:

  • You may need to define a new interface every time you need a callback function with new signature. Could partly be solved by making the interface class template
  • Each class that interested in callbacks needs to implement corresponding interface(s)
  • In some situations you may end up with a single object that can receive callbacks from many different publishers.

The last one could make you wish you never become a software programmer. The architecture, which seemed so beautiful just moments before, starts to fall into pieces once you find yourself in situation when you realize that your class-subscriber needs to receive same callbacks from different sources and act differently depending on who the caller is.

Let me explain it on the example. Imagine you have a class that implements that callback interface. You also have a lot of providers that take that interface to inform the subscribers, for example, about quote changes. But in your class, you need to track changes on, say, 10 quotes, and depending on which of those 10 changes, take different actions. So, what ’s your options?

Of course, you could just add an additional  parameter to callback method that specifies the sender, but it is not pretty at all, as the subscriber class now faces a new challenge of keeping track of all publishers it is subscribed too. Not mentioning the mess in the callback method needed to get all stuff to work!

Ideally, you want each of those providers to call different methods of your subscriber class, but in a general case it would mean 10 different interfaces and changes in all publishers, which may not be possible and I don’t even want to talk about it. The other option would be to write the proxy, which implements the basic callback interface, subscribes to the only provider and then re-routes the call to certain method on your class.

Thankfully, there is the far better option. boost::bind and boost::function are here to help.

class Publisher{
public:
typedef boost::function<void (int)> typeCallbackType;

void Subscribe(typeCallbackType cb)
{
m_cb = cb;
}

private:
typeCallbackType m_cb;

void SomeDataProcessingMethod()
{
// ....
m_cb(currentPrice);
}

}

And here is a good thing: your subscriber class does not have to implement any custom interface anymore:

class MySubscriber
{
public:
void CalledWhenPriceChanges(int newPrice)
{
// make profit here
}
}

to establish a subscription, simply use boost::bind:

Publisher* pPublisher = GetPublisherFor("someTicker");
MySubscriber Subscriber;

pPublisher->Subscribe(boost::bind(&MySubscriber::CalledWhenPriceChanges, &Subscriber, _1));

That’s all, folks!

Now, once the pPublisher has a new data, a CalledWhenPriceChanged() method of Subscriber instance of a class MySubscriber will be called. It is easy to see how additional publisher could be added if you want to monitor two tickers.

It would not only help solving the problem of multiple publishers-one subscriber. This approach will also do a great job saving you time from not having to define numbers of callback interfaces for different types of data that needs to be passed from publisher to subscriber.

Паттерн разработки: инверсия ответственности

Только что реализовал поддержку новой фичи в протоколе одного устройства.

Устройства самого еще в железе нет. Зато есть спеки. Благодаря им поддержка фичи уже есть где надо и как часы работает с симулятором, который тоже я реализовал по спекам.

Инверсия ответственности тут в том, что теперь в случае всяких непредвиденных обстоятельств (хотя какие они непредвиденные? Очень даже предвиденные – где это видано,чтбы железка на 100% соответствовала спекам?),  это именно железячные программеры будут допиливать свою железку, чтобы уже мой софт смог с ним работать. А не наоборот, как это чаще всего бывает при разработке клиентского софта для железок.

Чувствую себя по меньшей мере Доктором Зло.

Открытие

Предварительные результаты этой недели показали, что

  • Я далеко не самый худший GUI дизайнер в мире
  • C# и .NET я, оказывается, знаю на очень неплохом уровне. Не гуру, но если сравнивать с C++, то примерно на той же самой границе, после которой коллеги подходят и шепотом просят использовать поменьше шаблонов, а то они их боятся и поменьше паттернов вроде Обсервера, а то они их ниасилили.

Думаю, стоит попробовать себя в игре на рояле.

Технологии – вперде!

Интересно, что в C# настоятельно не рекомендуется вызывать виртуальные методы из конструкторов. По той же, в общем-то, причине, что и в C++.

Технологии технологиями, но фундаментальные вещи пропадать никуда не собираются.

9 visitors online now
9 guests, 0 members
Max visitors today: 15 at 09:10 am MST
This month: 23 at 05-03-2012 08:23 am MST
This year: 29 at 01-23-2012 02:50 am MST
All time: 45 at 02-23-2011 09:11 am MST