VTK/Wrapping C++11 Code
The purpose of this page is to track the status of C++11 support in the VTK wrappers.
Most VTK code follows the C++03 standard, and the oldest supported compiler is (I believe) Visual Studio .NET 2003. However, all VTK code is also compatible with C++11, and in fact VTK uses some features of C99 that were incorporated into C++11. Users of VTK have already begun moving their own code to C++11.
The following is a list of various new C++11 features to be supported. I will be adding these features to my WrapVTK project before moving them into VTK proper.
Current status: merged into master on 22 Nov 2013. To be released in VTK 6.1.
Closing angle brackets
Support code like std::vector<std::vector<int>> without requiring spaces between > and >.
Done.
Rvalue references
Use of "&&" to indicate an rvalue reference. As long as it is only used in assignment operators and copy constructors, I don't think the wrappers have to worry about the semantics, they just have to parse it. Are there bits available to represent it? It requires a modifier for "ref", and "const ref" already exists, so just as we use the CONST qualifier bit for "const &", we can have an "RVALUE" qualifier bit for "&&".
Done.
The constexpr keyword
Initially, this keyword can be ignored (until proper constant expression parsing is implemented).
Done.
New static_assert()
Uses of static_assert() can easily be removed by the lexer, though removing it in the parser is possible, too, with a little extra work.
Done.
Keyword decltype()
This provides the type of the expression in the parentheses. I can defer the type deduction (for templates, the type deduction will have to be deferred anyway). Deducing the type will require a complete constant_expression parser, which I don't have yet. I will probably implement the constant_expression parser as its own recursive descent parser, rather than implement it as part of the main yacc parser.
Done.
Method declaration with trailing return type
This is just a new function trailer, it will be easy to implement once decltype() is implemented.
template<class Lhs, class Rhs> auto add(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;}
Done.
Trailers final and override
These are trivial to implement because the wrappers can ignore the semantics. Though it might be useful for the wrappers to honor "final". Note: Unlike "throw" and "const", these are not keywords. They should be parsed as identifiers.
Note that "final" can be used in a class definition immediately after the class_id to declare that the class cannot be subclassed.
Done.
Trailer noexcept()
This goes along with the throw() trailer that already exists:
noexcept noexcept ( constant_expression )
Done.
Function bodies default, delete
Similar in syntax to the "= 0" body for pure virtual methods. In C++11, any method that the compiler can auto-generate (default constructor, copy constructor, destructor, assignment operator) can have its body replaced by "= default;" or "= delete;". The wrappers must honor these settings when it auto-generates these methods.
Done.
Auto variable type
For variables declared with "auto", the type will have to be deduced, in much the same way as is done with macro constants.
Done.
New literal nullptr
May require a new keyword, and a type constant for nullptr_t.
Done.
New string literal types
Prefixes "R", "u8", "u", "U". Plus, the prefix "L" is not implemented yet.
Done. Caveat: raw strings supported everywhere except for in preprocessor directives.
New char types
These are char16_t, char32_t, and also the pre-C++11 type wchar_t. Are these primitive types, or are they typdefs to a unique type, similar to nullptr_t? Or typedefs to a non-unique type, like size_t? I believe that wchar_t, at least, is required to be a primitive type. Unlike wchar_t and char, we at least know that char16_t and char32_t are unsigned. Also, in the C++11 standard (though not necessarily in pre-standard compilers) they are primitive types.
Done.
New string types
The C++11 library defines std::u16string and std::u32string. The wrapper parser recognizes std::string as a special type, but this should not be extended to u16string and u32string. They should not be special-cased within the parser code itself, it should be up to the wrapper back-ends like vtkWrapPython to recognize them and wrap them.
Not done, deferred.
User-defined literal suffixes
Tokenization of literals will have to be extended, and the new operator"" will have to be added. Capturing the literals as strings will be easy, but when I implement a constant_expression parser, these will have to be parsed whenever they are declared with constexpr.
Done.
New enum classes
Tricky, but they can still be considered to be enums. I'll have to add a type member to EnumInfo. The grammar will also have to allow for forward declaration of enums.
Done.
The thread_local storage specifier
This should be parsed and handled similar to static.
Done.
Explicit conversion operators
Implement "explicit" specifier for conversion operators. This is already parsed, so it is just a matter of setting the IsExplicit flag when the specifier is present.
Done.
Creating type aliases with "using"
using FunctionType = void (*)(double); template <typename Second> using TypedefName = SomeType<OtherType, Second, 5>;
Done.
Variadic templates
This will involve three pieces:
- parsing the template parameters
- parsing the pack expansions
- and, if variadic templates are ever to be wrapped, instantiation
Done.
Attributes
Attributes of the form [[name]], [[name(x,y)]], and alignas(type) will have to be parsed. A set of attributes can be defined for wrapping hints at some point in the future, but until then attributes can be ignored. If the attributes are hard to parse, then token sequence "[[" can be defined as a new token (allowing for space between the left brackets).
Done. Caveat: attributes are simply ignored.
Keyword alignof()
Operator alignof(type), e.g. alignof(int). It will have to be handled similarly to sizeof(), i.e. not at all until constant expression parsing is implemented.
Done.
C99 features
Specifiers _Alignas(), _Generic(), _Thread_local, _Noreturn.
Qualifer _Atomic.
Done.
Extern Templates
New "extern template" template declaration.
Done.
Lamdas
Lambda will not appear as part of class definitions, so they can be ignored.
Nothing to be done.
Variadic macros
If "..." ends a macro parameter list, then in the body of the macro __VA_ARGS__ should expand to the portion of the argument list that corresponds to the ellipsis.
Done, plus gcc and MSVC extensions.
New initializer syntax
C++11 has a new initializer list syntax:
int x {}; // default initialization (initializes "int" to zero) int x { 2 }; // equivalent to "int x = 2;" int x[3] { 1, 2, 3 }; // equivalent to "int x[3] = { 1, 2, 3 };" mystruct myval { "hello", "there" }; // equivalent to "mystruct myval = { "hello", "there" };" myclass myinstance { 1.0, 2.0 }; // equivalent to "myclass myinstance(1.0, 2.0);" std::vector<int> vec { 10, 11, 12 }; // a completely new form of initialization
Done.
Universal character names
Non-ascii characters can be specified, in strings and identifiers, via these codes, where x is a hexadecimal digit:
\uxxxx \Uxxxxxxxx
It's easy to handle these in strings, because they can be copied verbatim. Their use in identifiers is tricky, because the wrappers must be able to compare identifiers. So, when they appear within identifiers, they should be converted to the utf-8 encoding of the codepoint.
C++14 parsing
C++14 brings far fewer changes than C++11.
Template variable declarations
This should parse cleanly, with or without the "constexpr".
template<class T> constexpr T pi = 3.14159;
Template template declarations with typename
This should parse cleanly. In C++11 and earlier, it won't parse unless the final "typename" is replaced with "class'.
template<template<typename> typename X> struct D;
Binary literals
0b11100110 0b00011001
Apostrophe in numeric literals
1'000'000 0b0100'0001 1.345'234'543e10
C++17
"u8" prefix for character literals
For character literals, u8 means the character is unicode and fits in "char" (i.e. 8 bits). Hence, it is only useful for latin1 characters.
Parameter pack fold expressions
Parameter pack folding can take the following syntax:
- ( pack op ... )
- ( ... op pack )
- ( pack op ... op init )
- ( init op ... op pack )
These are used for evaluation, rather than declaration, so they require no changes to the parser.