piątek, 18 lipca 2014

Multi-argument constructors with default parameters & explicit keyword

Recently I was reviewing some snippet of code. It looked similar to following.

1 struct S {
2     explicit S(int someParam, int otherParam = 0) {
3         // Implementation...
4     }
5 };

At a glance I spotted the explicit keyword and wondered if it's needed. It's obvious that for one-argument constructors it is needed, if we don't want compiler to perform implicit conversions. However, what is the behavior when there's more than one arguments, but with default values?

I dig into the C++ standard and found relevant example [N3242] § 12.3.1/1. In the example there's a constructor accepting const char* as the first argument and int as the second one. The second one has default value of 0.

So the rule is that any explicit multi-argument constructors may become implicit if they have all but one arguments with default values.

poniedziałek, 9 czerwca 2014

flint: Facebook's C++ lint - compilation

Recently I read a post at Facebook Code about flint - yet another C++ linter. I though I could run this on our project to see whether it will outperform CppCheck. It was pain in the ass to compile this stuff. I hope this post will save your time, if you encounter similar problems.

folly
Folly is a C++ library used at Facebook. You can find details here. Without digging in one can discover that compilation instructions aren't descriptive enough. If you are running on Fedora 17 or Ubuntu 12.10 everything should compile as expected. Otherwise you have to pay attention which version of libraries folly depends on you download.

The first dependency is double-conversion. In the instructions it is said that if you have scons, you have double-conversion. This was not true in my case. I had to manually download it. I picked version 1.1.5, and apparently this is not the best one to pick. It doesn't compile at straight off. To make it working one must create symbolic magic link.

ln -s <double-conversion>/src/libdouble_conversion_pic.a <double-conversion>/src/libdouble-conversion.a

This is not the only link needed. The second one concerns header files.

ln -s <double-conversion>/src/ <double-conversion>/src/double-conversion

Now the compilation should go further. The next issue that occurred in my system was related to Google->opensource. Somehow I downloaded opensourced Gflags library, but the folly was still referring to Google one. Following one-liner helped to resolve this issue.

find . -name "*.cpp" -print | xargs sed -i 's/google::ParseCommandLineFlags/gflags::ParseCommandLineFlags/g'

flint
Here you should be prepared to install newer version of dmd, gdc, or ldc. Above find-replace command is also needed. The one thing that is wrong on flint GitHub page is missing dot after -L.

This way the executable comes, but running it gives segmentation fault. I figured out that CXX executable is working fine and it gives reasonable output. The D version seem to be broken.

If time permits I'll try to dig in and examine why. As always, you are welcome to share your ideas in comments.

Flint output looks very clear. In our project it found several problems, mainly related to non-explicit constructors, that may be accidentally treated as conversion constructors. Also, it was able to find header files without include guards (nice one!).

The last interesting that caught my eye is the following. It refers to SO ;)

/home/szborows/****.hpp(12): Warning: Protected inheritance is sometimes not a good idea. Read http://stackoverflow.com/questions/6484306/effective-c-discouraging-protected-inheritance for more information.

Update (10.06.2014, 01:32):
I managed to create valid D executable of flint through manually compiling newest version of dmd compiler and using it against flint.
There is no difference in output.

piątek, 18 kwietnia 2014

How it's made: C++ compilers - slides


As I recently wrote, yesterday I conducted a lecture about internals of C++ compilers for C++ Wrocław User Group. I'd like to share the slides with the world. You can access them here.

Unfortunately, audio mixer settings were broken, so the screencast is not published.





środa, 16 kwietnia 2014

Yet another interesting dark corner of C++

Dear C++ experts ;>:

Is following code correct or is it ill-formed?

typedef vector<int> Integers;

Surely, it isn't. What about following?

vector<int> typedef Integers;

Is it well formed? It turns out that it is. I've found this information here. I decided to dig in a little.
It seems that defining multiple type aliases for particular type is fine when the type is same for all aliases. For example, following snippet is not ill-formed:

typedef vector<int> Integers;
vector<int> typedef Integers;

This is suspicious, though. This is nearly the same what is used in Standard Template Library (STL), e.g. in initializer_list:

class initializer_list {   
public:
    typedef _E    value_type;
    typedef const _E&    reference;
    typedef const _E&    const_reference;

Here we can see that initializer_list defines reference and const_reference type aliases, but they actually are of same type. Actually this happened earlier in std::set, where both iterator and const_iterator are constant (otherwise a programmer could interfere on std::set internals).

The question is - in how many C++ places we can expect similar (unfamiliar) syntactical opportunities? Please share your ideas in comments. From my experience I can add the following.

struct S {
    void static const meth(int const) {}
};

The first interesting thing is that the static keyword occurs in quite weird place. The second thing, far more interesting is the const void type. There's no point to have such a type in C++ language. Or is it?



poniedziałek, 7 kwietnia 2014

C++11 quirk: Default c-tor & cv-qualified instances

Recently I found an interesting C++11 quirk.

http://jaredgrubb.blogspot.com/2013/05/c11-quirks-in-defaulted-functions.html

According to answers from the stack overflow it comes out that POD objects cannot be used with default constructors if you wish to create const instance of them. And it makes sense, as the const object cannot be changed in future.

The funny part is when you use `= default` outside of class body everything's fine.

Interestingly Clang compiler is again closer to the standard than gcc. It doesn't compile following code, whereas gcc does.

struct A { A() = default; }
int main(int, char) { const A a; }

Thanks to Jonathan Wakely it turned out that Clang behavior is the proper one. The C++ standard states:

"A special member function is user-provided if it is user-declared and not explicitly defaulted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed." [N3242, 8.4.2/4]


niedziela, 6 kwietnia 2014

How it's made: C++ compilers - Wrocław C++ User Group

Please feel invited to my presentation on C++ compilers' internals.

Place: University of Wrocław
Time: 17.04.2014

You can find more information here (PL).

sobota, 5 kwietnia 2014

Measuring C++ code quality - tools and techniques

My another article was published in last "Programista" journal. It is about tools and techniques that help measuring C++ software quality. It covers many practical aspects like code coverage, cyclomatic complexity, dependencies, etc.

Cover page