Примеры "современного С++" в действии?

Я использовал более "современные" С++-конструкции некоторое время, но вроде поверхностно и не везде. Я ищу проекты с открытым исходным кодом для изучения, которые являются хорошими примерами использования современных С++ и STL.

Такие вещи, как то, что предлагается в Meyer "Эффективный STL", например, попытка избежать циклов и заменить их более функциональными конструкциями, используя boost:: bind и boost:: function и т.д. Они все еще немного неестественны для я, и когда мне нужно что-то сделать быстро и работать, я склоняюсь назад к libc и string.h(у вас может быть мой strtok, когда вы вытаскиваете его из моих холодных, мертвых рук).

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

Можете ли вы порекомендовать несколько примеров хорошо написанных проектов с открытым исходным кодом, которые сильно используют STL и другие современные методы С++, которые я мог бы изучить? Меня особенно интересует код приложения, просмотр источников boost был полезен, но по необходимости очень общий, потому что это код библиотеки.

Я интересуюсь проектами средних и крупных проектов, по крайней мере, несколькими десятками тысяч строк. Это довольно легко найти примеры, которые состоят из нескольких сотен строк, но это не слишком полезно.

Ответ 1

Здесь вы найдете несколько интересных примеров того, как Boost используется в проектах с открытым исходным кодом:
http://www.boost.org/users/uses_open.html

Ответ 2

Мейерс в порядке, однако, если вы действительно хотите подтолкнуть себя, вы должны прочитать

Andrei Alexandrescu - Современный дизайн С++: разработаны типовые шаблоны программирования и дизайна

Это сдует ваш ум. То, что вы узнали в книге, описывает библиотеку Loki.

Один из моих фаворитов - это int для преобразования типов:

template <int v>
struct Int2Type
{
    enum { value = v };
};

Я использовал его в прошлом для моей библиотеки сериализации XML С++ для предварительного выделения вектора < > перед загрузкой данных:

// We want to call reserve on STL containers that provide that function,
// namely std::vector.
// However, we would get a compiler error if we tried to call reserve on
// a STL container that
// did not provide this function. This is the solution.
template <bool b, class T>
class CReserve
{
public:
    static void reserve(T &lst, const int &n)
    { reserve(lst, n, Loki::Int2Type<b>()); }

private:
    static void reserve(T &lst, const int &n, Loki::Int2Type<true>)
    { lst.reserve(n); }

    static void reserve(T &lst, const int &n, Loki::Int2Type<false>)
    { (void)lst; (void)n; }
};

Обратите внимание на частные специализации выше. Хорошо, если вы внимательно присмотритесь, один вызывает reserve(), другой - нет. Это специализированная специализация с использованием bool в качестве типа.

который в tern используется:

template <bool bCallReserve, class T>
bool STLSerializeClassType(MSXML::IXMLDOMNodePtr pCurNode, T &lst, 
                           CXmlArchive &archive, const char *name)
{
    if(archive.IsStoring())
    {
        ...
    } else {
        lst.clear();

        T::size_type nCount(0);
        XML_ELEMENT(nCount);

        CReserve<bCallReserve, T>::reserve(lst, nCount);

        while(nCount--)
        {
            T::value_type temp;
            temp.SerializeXml(archive, pCurNode);
            lst.push_back(temp);
        }
    }
}

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

#define SERIALIZE_XML_STL_CLASS(list_name, bCallReserve) \
(HS::STLSerializeClassType<(bCallReserve)>
    (pCurNode, (list_name), archive, (#list_name))
)

поэтому в коде вы будете использовать что-то вроде:

std::list<CFred> fredList;
SERIALIZE_XML_STL_CLASS(fredList, false);

или для векторов:

vector<CFred> fredList;
SERIALIZE_XML_STL_CLASS(fredList, true);

Во всяком случае, я перестану вибрировать... Это просто для простого использования простого шаблона Int2Type < > . Там много умных вещей, таких как получение компилятора для вычисления тонны материала за счет умного использования перечислений. Поистине ужасная книга.

Ответ 3

На самом деле, я просмотрел Google Chrome и рекомендовал бы его. Кодирование Google С++ рекомендации - хороший эшафот для крупного проекта. Они также используются и приняты в нашей команде. Более того, я очень рад, что они предоставляют свои С++ насмешка и тестирование в качестве проектов с открытым исходным кодом. Очень удобно для крупных проектов, где вы пропускаете много приятных тестовых материалов из Java/Managed world.

Ответ 4

На самом деле не проекты, но вот несколько фрагментов:

Пример использования boost:: thread/boost:: bind:

class X { void expensive_operation( int argument ); };

int main()
{
   X x;
   boost::thread thr( boost::bind( &X::expensive_operation, &x, 1000 ) );
   std::cout << "Thread is processing..." << std::endl;
   thr.join();
}

std:: copy, std:: transform, BOOST_FOREACH:

int main()
{
   std::vector<std::string> v;
   std::copy( std::istream_iterator<std::string>( std::cin ), 
              std::istream_iterator<std::string>(), std::back_inserter(v) );
   BOOST_FOREACH( std::string & s, v )
   {
      transform(s.begin(), s.end(), s.begin(), toupper);
   }
   std::copy( v.begin(), v.end(), 
              std::ostream_iterator<std::string>(std::cout, " ") );
}

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

В наших приложениях интенсивно используются функции boost:: signals и boost:: function, чтобы разделить классы, где это не критично, главным образом в классах пользовательского интерфейса:

class ContactDetailPanel;
class ContactListPanel {
public:
   void update();
   void edit_completed( bool change );
   boost::function< void ( Contact & ) >& edit_contact();    
};
int main()
{
   ContactListPanel clp;
   ContactDetailPanel cdp;

   clp.edit_contact() = boost::bind( &ContactDetailPanel::edit, &cdp, _1 );
   cdp.edit_completed() = boost::bind( &ContactListPanel::edit_completed, &clp, _1 );
   ui::signal_update().connect( boost::bind( &ContactListPanel::update, &clp ) );     
}

Каждая панель не имеет информации о других панелях. Код, который связывает панели вместе, имеет знание потока (для редактирования панели сведений о контактной контактной информации, уведомление о завершении редактирования на панели списка контактов). Кроме того, существует глобальный сигнал для уведомления панелей обновлений базовой модели.

Это особенно полезно, когда вам нужно написать тестовый код. Нет необходимости внедрять макеты для замены рабочего кода для тестирования. Тесты просто создают экземпляр класса и соединяют функции/сигналы для проверки кода без проверки класса, следуя принципу наименьшего вторжения во время тестов.

Ответ 5

Я не уверен в "хорошо написанном", но есть несколько вещей, вроде Hypertable и KFS, которые являются системным программным обеспечением, которое использует Boost и STL экстенсивно.

Я слышал кое-что о OpenOffice и Google Chrome, но я не смотрел их исходный код, чтобы узнать, как именно они используют STL. Я заглянул в KDE, но я не стал бы называть этот современный С++. Я могу сказать вам, что некоторый код, над которым я работаю, - это много современных С++, но, увы, это не открытый исходный код, хотя я считаю, что это всего лишь вопрос времени и терпения, чтобы получить современный С++-подход и иметь больше проектов с открытым исходным кодом принимая идиомы.

Ответ 6

В последние пару лет Adobe опубликовала много современного открытого кода на С++, что, вероятно, стоит проверить:

http://opensource.adobe.com/wiki/display/site/Home

Я считаю, что их библиотека GIL либо была, либо находится в процессе добавления в Boost. их STLab содержит тонну функциональности, которая, из того, что я видел, очень чиста и очень похожа на STL-стиль.

Ответ 7

Вот фрагмент, чтобы объединить вектор строк в одну строку:

vector<string> vecstr;
vecstr.push_back("abc");
vecstr.push_back("efg"); // etc.
string concat = accumulate( vecstr.begin(), vecstr.end(), string("") );