Category Archives: C++

Controlling C++ macro expansion – WG21/N3400

Macros are a bane of library code writers’ lives. They are also still essential, and can’t be disposed of.

WG21/N3400, A proposal for eliminating the underscore madness that library writers have to suffer, is a proposal to control macro expansion in header files. This is long overdue. It’s also simple enough that it might get into the next standard. Basically, macros have priority levels, files have priority levels, and a macro with a lower priority is not expanded when it occurs as an identifier in a file with a higher priority level.

Now, that said, it’s too cautious about “implementation-defined manner”. This is something that can have more definition, because there’s not existing practice to preserve, and this is at the source level, so there’s little to worry about in terms of efficiency (the usual reason why “left to the implementation” exists in the first place).

For example, the proposal is that “how priorities are determined is implementation defined”, but that goes at odds with those of us who like to write cross-platform code. Also, it just says that “recommended at least 3 priority levels exist”, but that’s weak because it assumes there are just three categories of user source, first/third party libraries, and implementation libraries. The reality is more nuanced than that.

However, I like the idea of macro priority – it’s simply the priority of the file it is defined in, or re-defined in (and priority can only increase, not decrease).

The entire point is that, if I write a library and give it to someone to use, its header files aren’t affected by macros defined by other headers that happen to be included first. For non-macros, this is already handled well by namespaces.

I need to write a counter-proposal, or a critique of the proposal.

C++ brace initializers

C++ added a new aggregate initialization syntax, and it works for simple types as well. One advantage to it is that it forbids narrowing conversions.

If you have this code

    float f(0);
    int i{f};

then you’ll get this compile error in the latest Visual C++ compiler (the Nov 2012 release), which is mostly C++11 compliant.

1>urltests.cpp(73): error C2440: 'initializing' : cannot convert from 'initializer-list' to 'int'
1>          list-initialization requires a narrowing conversion from 'float' to 'int'

The VC compiler error is poorly worded, but basically lets you know that you did something that’s probably bad.

Yes, you would get a warning in normal cases, but you can disable warnings or ignore them – you can’t disable errors. I prefer errors :)

It won’t be that hard to get used to the syntax, and it’s another reason to stop using pre-C++11 compilers.

Reference

http://stackoverflow.com/questions/9976927/when-to-use-the-brace-enclosed-initializer

C++ templates and writing more natural code

A long time ago, you could write this

char * buf = malloc(1024);

This is because malloc returned void *, and in C, you could assign a void * to any other pointer, as a convenience. It was thought of as a generic pointer, so you could make it concrete by assigning it. And of course, you can’t go the other way without an explicit cast.

This stopped working in C++ because implicit conversions cause problems with explicit conversion operators, single-argument constructors and the like; the language designers had to allow char/short/int implicit conversions to continue to happen because too much code would break, but breaking the generic nature of void * wasn’t all that bad. Still, I liked it.

You can simulate this behavior in C++ as follows.

class voidp {
    void * ptr;
public:
    voidp(void * arg) : ptr(arg) {}
    template<class T> operator T * () { return reinterpret_cast<T *>( ptr ); }
};
voidp voidp_malloc(size_t bytes) { void * ptr = (malloc)(bytes); return ptr; }
#define malloc voidp_malloc
char * buf = malloc(1024); // works in C++ now!

This works by having a non-explicit one-argument constructor to do automatic type conversion to a voidp from a void *, and then a conversion operator to deduce the return type and cast to it.

Implicit conversions are dangerous, and so you want to be careful about them. In fact, I wish I could have integral types that didn’t have implicit conversion to other integral types, but the state of the art in optimizing compilers doesn’t allow for this to be done without overhead, and doing it requires either lots of verbose code, or some macros. Matthew Wilson outlined how to do this in his book Imperfect C++ – you use templates to create types, and then explicit conversion operators to manage conversions between those types.

Boost added BOOST_STRONG_TYPEDEF written by Robert Ramey with a very different approach, and different philosphy – Matthew Wilson’s approach made types that were not convertible at all, whereas BOOST_STRONG_TYPEDEF creates types strong enough that you can overload on them, but implicit conversion still happens when you assign them, use operators on them etc. So I’d call it a half-strong typedef. In fact, the author recently posted a message to the std-proposals newsgroup a message stating that the half-open nature of BOOST_STRONG_TYPEDEF meant it didn’t work out as intended, and he now uses a strong approach probably similar to what Matthew Wilson was advocating: see https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/GP2Crh9hY84

And now that we have rvalue references, maybe all of this can be super-efficient for making strong typedefs of integral types. The issue with Matthew Wilson’s approach was that a strong typedef on a 4-byte type resulted in math on pointers to types – hidden from C++ code, but meaning imposition of a runtime overhead.

There was some talk in the C++ committee of having a “strong typedef” added to the language (typedef doesn’t actually create new types, it just creates synonyms for types). It didn’t happen for C++11, but it has been resurrected as “opaque typedefs”, see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3515.pdf. I like the terminology in the paper: classic typedefs are “transparent type definitions” that introduce new type names but not new types, and stronger typedefs can be created with a opaque alias facility

Reference

ISO C++ Standard – Future Proposals, news group.

Toward Opaque Typedefs for C++1Y, WG21/N3515, Walter Brown, 2013.

Using variadic templates (C++11)

In C++11, I write this:

template <typename FuncPtr, typename ReturnType, typename... Arguments>
ReturnType CallWin32DllFunc(char * lib, char * entry, Arguments... args)
{
    HMODULE lib = GetModuleHandleA(lib);
    FuncPtr fn = (FuncPtr) ::GetProcAddress(lib, entry);
    if (fn == NULL) return (ReturnType) 0;
    return fn(args...);
}

The idea is that you can call Windows functions that aren’t statically linked into your program. I’m glossing over some error-handling details, but you’d call it like this

    MEMORYSTATUSEX memx = { sizeof(MEMORYSTATUSEX) };
    BOOL ok = CallWin32DllFunc<BOOL (WINAPI *)(MEMORYSTATUSEX *), BOOL>(
                   "kernel32.dll", "GlobalMemoryStatusEx", &memx);

Surprisingly, I understand variadic templates enough that this works. Next steps are to do some runtime error handling, a void return overload, and return type deduction (write a class with a function operator?).

Reference

Variadic Templates: Exploring the Design Space – N1704=04-0144,Douglas Gregor, Jaakko Jarvi, Gary Powell, 2004.

A Brief Introduction to Variadic Templates – N2087=06-0517, Douglas Gregor, 2006.

Proposed Wording for Variadic Templates – N2242=07-0102, Douglas Gregor, Jaako Jarvi, Jens Maurer, Jason Merrill, 2007

Variadic Templates for GCC, Douglas Gregor, 2007

Extending Variadic Template Template Parameters – N2555=08-0065, Douglas Gregor, Eric Niebler, 2008

tinyformat.h. A minimal type safe printf-replacement library for C++, using variadic templates.

C++0x Compiler Support – Apache keeps track of C++11 compliance in the various compilers.

Implementing COM Interfaces with C++0x Variadic Templates, Kirill Osipov, CodeProject, 2011.

C++11 – New features – Variadic templates, Henri Korpela, cplusplus.com, 2012.

Variadic template, from Wikipedia.

C++11 – remove_const, add_const

remove_cv reference

Templates can manipulate types. It’s straightforward to add adornment to types, but you can also remove them. The basic ones to remove are const and volatile. Fist, let’s look at remove_const:

template <class T> struct remove_const          { typedef T type; };
template <class T> struct remove_const<const T> { typedef T type; };

This works by partial specialization. For a type E that can be defined as typedef const T E, remove_const<E> will match const T, and thus T will be the type E with const removed. Otherwise, the default template will match, and T will be the type E.

The other qualifier is volatile, and it works exactly the same way.

template <class T> struct remove_volatile             { typedef T type; };
template <class T> struct remove_volatile<volatile T> { typedef T type; };

Combining them together to remove both const and volatile is only slightly tricky, and not because there is any ordering of const and volatile.

You might assume this would work

template <class T>
struct remove_cv {
    typedef remove_volatile<remove_const::type>::type type;
};

This fails, but for the simple reason that the compiler doesn’t know that remove_const::type is actually a type at the point of parsing. A GLR parser could figure this out, but an LL or LR parser has an even harder time than normal; even with ordinary typedefs, there is unavoidable feedback between syntactic parsing and semantic parsing, almost always accomplished by giving the syntactic parser access to the symbol table. Templates complicate this, and most C++ compilers need hinting. This is why the typename keyword has to be employed at times; this tells the compiler that the next element is a type. So we need to put typename in two strategic places, like so:

template <class T>
struct remove_cv {
    typedef typename
            remove_volatile<typename
                            remove_const<T>::type
                           >::type
            type;
};

The indentation is to show each piece of the template more clearly.

While the standard says “removes the topmost const, volatile or both”, you can only have one each of const and volatile attached to a type – there is no “const const T”.

Adding const is easier than removing it

template <class T> struct add_const { typedef const T type; };

Since you can only have one const at any level of a type, adding const to const is harmless, and thus there is no need for multiple specializations of add_const. Similarly, add_volatile and add_cv will look familiar:

template <class T> struct add_volatile { typedef volatile T type; };

template <class T>
struct add_cv {
    typedef typename add_volatile<typename add_const<T>::type>::type type;
};

C++11 – enable_if

I’m going to try to write readable and yet performant (and conformant) implementations of a few of the most useful templates.

enable_if from cppreference
enable_if Boost documentation

The enable_if template is used with SFINAE – “substitution failure is not an error” – in order to be able to pick which template to expand. This can be used in simple cases to allow overloading on types that would otherwise have implicit conversion (int to float, for example), or to avoid integral promotion (short to int, for example) that would otherwise prohibit template specializations, or even as a return type (allowing specialization on return type that would otherwise be impossible).

template<bool CONDITION,
         class T = void>
struct enable_if {};

template<class T>
struct enable_if<true, T> { typedef T type; };

The specialized version enable_if<true, T> declares a type enable_if<T>::type, which is just T.

The non-specialized enable_if doesn’t declare a type, which means that code that selects the non-specialized version won’t instantiate. Of course, if no other templates match, you’ll get a compile error, but in general the point is to write useful code. I cribbed the “class T = void” bit from the definition of enable_if, and I need to figure out why it’s necessary. All I can see is that it makes it legal to write enable_if<false> and not need to write enable_if<false, T>. There must be a usage case where that is convenient to do. And, it seems like the answer is from Boost. Once upon a time, there were three variants of enable_if, but the C++ committee picked just one, what Boost called non-lazy. Also note that Boost used enable_if_b for the variant that in C++11 is called enable_if. This means that Boost.MPL needs the Boost version of enable_if, not the standard C++11 version. Although, is it possible that enable_if<class Cond> can interoperate with enable_if<bool B>?

And so, we find out that the default void parameter allows us to write enable_if as a dummy parameter to a function, which allows for template SFINAE to accept or reject that entire function definition based on whether the dummy parameter compiles or not. That would look like this:

template <class T>
T foo(T t, typename enable_if<BOOLEXPR>::type * dummy = 0);

This lets one omit the type parameter, which is a small thing but might increase clarity. Presumably with a decent compiler, the unreferenced parameter is compiled out, resulting in no extra code.

This is one of the simplest useful template metaprogramming methods, and is the basis of things like type traits. Also, enable_if combined with recursion is what turns templates into a Turing-complete language.