VTK/Wrapping C++11 Code

From KitwarePublic
Jump to navigationJump to search

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.