C++ traits revisited


My previous entry on traits in C++ was a reasonable start but it missed one important corner case—namely classic C++ enums—and adopted the nonstandard approach of parameterizing the algorithm class on the traits type as opposed to the operand class. Here is a revised sample that addresses these two points:

Traits with enums

Class C++ enums suffer from a name scoping issue which complicates traits a little: enum members result in names that are injected into the enclosing namespace and that are not scoped by the name of the enum type itself. This means that we cannot refer to these constants in algorithm code via the enum typedef. I scratched my head about how to overcome this difficulty and, in the end, the only solution I could come up with was to emit static consts for each member of each enum into the partially specialized traits classes. In my particular case, these enums correspond to code that is generated by a tool, so I was simply able to modify the tool to generate part of the partial template specializations, hence the source code comments.

Note that this problem is solved by “enum classes” in C++11 where the members are scoped within the name of the enum itself. When using this language feature, we can remove the static consts altogether and refer to the members via the enum’s typedef.

Parameterizing on operand type

Most real-world examples of traits usage in C++ parameterize the algorithm class on the operand type as opposed to the traits type itself. Hence, this updated sample declares template<typename Tree> class Algorithm as opposed to template<typename Traits> class Algorithm in my original posting.

Tags: Design patterns, C++

All content © 2017 Richard Cook. All rights reserved.