Home » C++ » Examples of “modern C++” in action? [closed]

Examples of “modern C++” in action? [closed]

Posted by: admin November 29, 2017 Leave a comment

Questions:

I’ve been using more “modern” c++ constructs for a while, but kind of superficially and not everywhere. I’m looking for open source projects to study that are good examples of Modern C++ and STL usage.

Things like what is suggested in Meyer’s “Effective STL”, such as trying to avoid for loops and replace them with more functional constructs, using boost::bind and boost::function, etc. These still feel a little unnatural to me, and when I have to get something done fast and working, I tend to drop back to libc and string.h (you can have my strtok when you pry it from my cold, dead, hands).

However, I’ve also had the positive experience of finding what would be a drastic change simplified because I’ve used these constructs, or being able to implement something with just a few lines of code because I had the right operators and functors lying around. In addition, I’ve recently been paying more attention to concurrency, and so this is becoming even more important to me.

Can you recommend some examples of well-written open source projects that make heavy use of the STL and other modern c++ techniques that I could study? I’m particularly interested in application code, browsing the boost sources has been helpful but it’s by necessity very general because it’s library code.

I’m interested in medium sized to larger projects, at least a few tens of thousands of lines. It’s pretty easy to find examples that are a few hundred lines long but that’s not too helpful.

Answers:

Here, you find several interesting examples of how Boost is being used in open source projects:
http://www.boost.org/users/uses_open.html

Questions:
Answers:

Meyers is ok, however, if you really want to push yourself, you have to read

Andrei Alexandrescu – Modern C++ Design: Generic Programming and Design Patterns Applied

It will blow your mind. What you learn in the book describes the Loki library.

One of my favourites is the int to type conversions:

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

I’ve used it in the past for my C++ XML serilisation library for pre-allocating vector<>’s before loading them with data:

// 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; }
};

Notice the private specialisations above. Well if you look closely, one calls reserve(), the other doesn’t. This is a template specialisation using a bool as a type.

which in tern is used by:

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);
        }
    }
}

To make things simple in users C++ code, I added a lot of helper definitions

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

so in your code you’d use something like:

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

or for vectors:

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

Anyway, I’ll stop wittering on… Thats just putting the simple Int2Type<> template to good use. There’s loads of clever stuff like getting the compiler to compute a ton of stuff beforehand by clever use of enums. Truly awsome book.

Questions:
Answers:

Actually, I had a look into Google Chrome and would recommend it. Google’s C++ coding guidelines are a good scaffold for large project. They are used/adopted in our team, too. Moreover, I am very happy that they are providing their C++ mocking and testing frameworks as open source projects. Very handy for large projects where you miss a lot of the nice test stuff from the Java/Managed world.

Questions:
Answers:

Not really projects, but here are a couple of snippets:

Sample use of 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, " ") );
}

The snippet will read from user input a set of strings into a vector. Then for each string in the vector it will convert to upper case and finally output the result.

Our applications make heavy use of boost::signals and boost::function to decouple classes where it is not time critical, mainly in UI classes:

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 ) );     
}

Each panel has no information about other panels. The code that binds panels together has the flow knowledge (to edit a contact use contact detail panel, notify edit completion to contact list panel). Also, there is a global signal to notify panels of updates to the underlying model.

This is specially helpful when you need to write test code. There is no need to implement mock classes to replace working code for testing. Tests just instantiate the class and connect the functions/signals to test code without the tested class noticing, following the principle of least intrusion during tests.

Questions:
Answers:

I’m not sure about “well written” but there are a few things out there like Hypertable and KFS that are system-level software that both use Boost and STL extensively.

I have heard some things about OpenOffice and Google Chrome but I haven’t looked at their source code to know how precisely they use the STL. I’ve peeked at KDE but I wouldn’t necessarily call that modern C++. I can tell you that some code I’m working on is doing lots of modern C++ but alas it’s not open source — although I think it’s just a matter of time and patience to get the modern C++ approach out and have more open source projects adopting the idioms.

Questions:
Answers:

Adobe has published a good deal of modern C++ open-source code in the last couple of years, which is probably worth checking out:

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

I believe their GIL library either has been, or is in the process of being added to Boost.
their STLab contains a ton of functionality too which, from what I’ve seen is very clean, and very much STL-style.

Questions:
Answers:

Here is a snippet to concatenate vector of strings into one string:

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