shared_ptr almost like intrusive_ptr

The current C++11 Standard consists of a very important remark in section 20.9.11.2.6. It is about creation of shared_ptr object. The remarks state:

Implementations are encouraged, but not required, to perform no more than one memory allocation.
[Note: this provides efficiency equivalent to an intrusive smart pointer. end note]

At work [1], I use Visual C++ 2010+ implementation of C++. I couldn’t resist myself to check if the standard managed to encourage Stephan T. Lavavej (STL) and his team at Microsoft to go for this optimisation.

I compiled and run a quick test:


#include <memory>
int main()
{
    std::shared_ptr<int> p0(
       new int(3)); // #1

    std::shared_ptr<int> p1
        = std::make_shared<int>(3); // #2
    return 0;
}

Quick check using breakpoints confirmed that Visual C++ 2010 indeed optimises construction of the shared_ptr. The difference between #1 and #2 is an important one: the second version causes 50% less memory allocations than the first one. Namely, one allocation. std::make_shared packs bookkeeping data and the user-defined data into a single block of memory.

Know your tools or suffer fragmented.

GCC At Home

I couldn’t leave a blog post alone without some kind of unrelated off-topic and pointless digression. So, here is one: Stephan T. Lavavej on his homepage provides custom-built distribution of MinGW toolset with What MinGW Is section starting as follows:

I recommend that anyone who is learning Standard C++ and who uses Windows for a primary development environment should use two compilers: the most modern version of Microsoft Visual C++ (currently 2010 SP1) and the most modern version of GCC, the GNU Compiler Collection.

Stephan works at Microsoft. I admire this kind of professionalism free from strategically competitive marketing b******t. GCC should definitely be included in the list of New Seven Wonders of the World. Recently, a new wonder has emerged: LLVM/Clang. I’m a user of all the three compilers (and related toolsets). It is easy for me to dream about Visual C++Visual Studio IDE based on LLVM/Clang as C++ compiler and shipped with C/C++ standard libraries provided by GCC. That would be a real C++ Renaissance

Boost.Geometry and macros made by Apple

Boost Geometry (aka Generic Geometry Library, GGL)I have no pleasure continuing my macros are evil tales but the life of C++ programmer eagerly wants to writes add another chapter to the story. Today, it’s time to rant on Apple and its XCode.

One of Boost Geometry (aka GGL) users, Mark, reported that he can not compile his program using the library with GNU C++ compiler from XCode. The compiler throws mysterious complain of a very low-level nature of C++ programming language:

Expected unqualified-id before 'do' in
/usr/local/include/boost_1_42_0/boost/geometry/geometries/concepts/check.hpp

Thanks to follow-up by Stjepan we quickly know who to blame for that. It is XCode header AssertMacros.h. It even might be one of public headers from development package of XNU, the Mac OS X kernel, what’s even more fun.

What actually happens that causes the problem?

Boost Geometry defines function template for concept checking:

template <typename Geometry>
inline void check()
{
    detail::checker<Geometry, boost::is_const<Geometry>::type::value> c;
    boost::ignore_unused_variable_warning(c);
}

Apple XCode defines macro using exactly the same name as the function check. The C++ preprocessor, which operates before compiler, substitutes the name check with content of the macro. For the Boost Geometry function check it means that a pile of garbage is injected in place were the function name is expected:

template <typename Geometry>
inline void do { if ( __builtin_expect(!(), 0) ) { DebugAssert('?*?*',
0, "Third Party Client" ": " "", 0, 0, "/usr/local/include/boost/
geometry/geometries/concepts/check.hpp", 181, (void*)0); } } while ( 0 )
{
     detail::checker::type::value> c;
     boost::ignore_unused_variable_warning(c);
}

Obviously, it makes compiler to give up to instantiate the check function from the template and to compile it properly.

C/C++ macros are evil, however, not by design but by insanity of programmers. Every macro defined in a public C/C++ header, should be defined using as unique as possible, but still usable name. I wish Apple folks designed their C/C++ macros as unique as they make their hardware products, even if made in China eventually. This particular macro that caused the problems discussed here, could be named to APPLE_XNU_CHECK and life would be easier. Or, given the fact that almost 3000 files using these identifiers live in Boost C++ Libraries only, I probably should say: life would be more productive, efficient and cheaper.

By the way, it’s a known problem @ Boost and it looks Boost Folks are trying to figure out best solution. See ticket #2115 – Avoid bad Apple macros.

…to be continued

Traits of void resolved

It looks like I’ve got clarified status of the traits of void type. I posted my question to libstdc++ where Paolo Carlini kindly provided me what the bits I have been missing. Now, all the puzzles are in place:

[n1836], the specifications for the TR1 features mandates true for is_pod<void>, etc. Arguably this is a defect, which has been fixed in the ongoing work for the next standard, so-called C++0x.

The TR1 document in section 4.9 states:

8 It is unspecified under what circumstances, if any, is_pod::value evaluates to true, except that, for all types T:

is_pod<T>::value >=
   (is_scalar<T>::value || is_void<T>::value);

Given that, the bug report ID:458570 I submitted to Visual C++ 9.0 and it’s TR1 implementation on Microsoft Connect stays valid and according to what Stephan T. Lavavej confirmed in comments to my report, it’s been fixed in Visual C++ 10.0.

Paolo also added a note particularly important to programmers relying on C++ implementation by GCC compiler and libstdc++ library:

In general, we consider TR1 essentially frozen at this time and minimally maintained, consider that it was just an interim Technical Report

Here are references that are fundamental for the matter:

  • n1836 – Draft Technical Report on C++ Library Extensions
  • n2960 – Working Draft, Standard for Programming Language C++
  • Implementation of is_pod<T> and the rest of type traits by Boost.TypeTraits library.

Mission accomplished ;-)

Traits of void

Long time ago, I reported bug to Visual C++ 9.0 (Visual Studio 2008 SP1) complaining that has_trivial_destructor applied to void returns true (ID:458570). I also discussed it with folks on comp.std.c++ where, among quite different voices, Pete Becker writes:

[tr.meta.req]/8 in TR1 requires is_pod::value to be 1. n2857 is not a standard, and implementations of previous standards are not wrong for not doing what isn’t yet required of them.

and later concludes:

Under the current standard, using the name std::is_pod requires a diagnostic. So if you want to be literal, both compilers are “wrong”. Nevertheless, neither is really “wrong”, they just implement different non-standard versions of is_pod.

So, Visual C++ might actually not be wrong. Fair enough.

Today, I got back to this issue for a while a little extending my test program to use the type traits from both, TR1 and C++0x:

#include <iostream>
#include <tr1/type_traits>
int main()
{
using std::cout; using std::endl;
cout << std::tr1::is_pod<void>::value << endl;
cout << std::tr1::has_trivial_destructor<void>::value << endl;
cout << std::is_pod<void>::value << endl;
cout << std::has_trivial_destructor<void>::value << endl;
}

and compiled it with GCC 4.4.1:

$ g++ -Wall -pedantic -std=c++0x void.cpp
$ ./a.out
1
1
0
0

Now, my confusion has been raised to the power of 2. This is clearly a Polnische Wirtschaft or Czech movie or Turkish sermon

…let’s try to ask libstdc++ folks.

Inconsistent int64_t definition in GCC?

While compiling programs on Linux 32-bit with Comeau C/C++ 4.3.10.1 front-end and GCC 4.3.3 I encountered some problems using Boost Integer library, namely boost/cstdint.hpp header. Here we go:

If I first include sys/types.h (added with POSIX), directly or indirectly, and then include boost/cstdint.hpp in C++ program:

#include <sys/types.h>
#include <boost/cstdint.hpp>
int main()
{
    boost::int64_t a(0);
}

then it does not compile:

$ como -I/home/mloskot/dev/boost/_svn/trunk test1.cpp
MODE:non-strict warnings C++ noC++0x_extensions
"/home/mloskot/dev/boost/_svn/trunk/boost/cstdint.hpp", line 111: error: the
          global scope has no "int64_t"
    using ::int64_t;
            ^
"bad.cpp", line 5: error: namespace "boost" has no member "int64_t"
      boost::int64_t a(0);
             ^

Then, if stdint.h (added with C99) is included first (again, directly or indirectly), then the program compiles without any errors:

#include <stdint.h>
#include <boost/cstdint.hpp>
int main()
{
    boost::int64_t a(0);
}

It turns out that there is some amount of overlap in the stdint.h and sys/types.h headers. The issue is that the overlapped parts slightly differ. For the architecture, operating system and compilation toolset I use, both headers define int64_t type as follows:

typedef long long int int64_t;

However, the definition in sys/types.h header is guarded with different preprocessor condition testing __GLIBC_HAVE_LONG_LONG:

#  elif __GLIBC_HAVE_LONG_LONG
__extension__ typedef long long int int64_t;
#  endif

If I change sys/types.h replacing the clause with simple #else:

#  else
__extension__ typedef long long int int64_t;
#  endif

then the first variant of my program, the one including sys/types.h, does compile perfectly well.

Now, is this small difference a bug in the GNU C Library?
I’m going to try to confirm it.

Portability poem

Meaning of PortabilityNumber of OSGeo stack software written by C/C++ camp have to run on Microsoft Windows systems. I think I wouldn’t be dead wrong if said that most of hackers from OSGeo Community work on Unix systems (Linux, Mac OS X) but there is large number of users who work on Windows.

Conclusion? Portability. Google is bursting at the seams of the essays about how to write portable code in C or C++ language. I’d add a little poem to the collection.

Principles of Portability

  • Obey the standards, because they are not just dumb rules.
  • Make a list of compilers that must be supported. Learn about their differences.
  • If possible, use GCC 4+ and Visual C++ 7.1+.
  • Using old compilers? If possible, use C89 but avoid C99.
  • Prefer GCC 4.3 and Visual C++ 8.0+, so you get C++0x support. C++0x “brings C++ more in line with the C99″ – Wikipedia, so portability is much easier.
  • Write code in C or in C++, but do not write both at the same time.
  • Avoid (direct) use of C POSIX Library.
  • Never ever disable any warnings compiler throw. Fix them.
  • Be pedantic. Compile in highest strict mode possible.
  • If possible, do not use compiler-specific features.
  • Do not make platform/architecture specific assumptions about memory addressing, memory layout, etc.
  • First understand why, then cast the hack.
  • Personal preferences are evil. Make decisions based on reasoning.
  • (Re)Use good code that already exist. Boost C++ Libraries won’t bite you!
  • KIMS (Keep it modular, stupid) and let modules to loose coupling but keep cohesion in architecture, design as well as in development cycle (releases, inter-modular dependencies).

Got new toy

I’ve just got new toy tool. Since yesterday, I’m a happy owner of the most standards-conformant C++ compiler that ever existed – Comeau C/C++ from Comeau Computing.

I’ve successfully installed Comeau C/C++ 4.3.10.1 Beta compiler and libcomo36, accompanying Standard C++ Library, on 32-bit version of latest Ubuntu 9.04.

I’m going to use Comeau C/C++ for purposes like analysis and review of C++ source code I write or use, verification of code portability as well as for learning elements of C++ and experimenting. This is excellent compiler for learning C++ language. Among loads of features, one of the coolest is ability to give clear and informative error messages. This is very helpful while working with complex class and function templates.

Continue reading