C++20 Concepts Are Here in Visual Studio 2019 version 16.3

September 10th, 2019

C++20 Concepts are now supported for the first time in Visual Studio 2019 version 16.3 Preview 2. This includes both the compiler and standard library support.

First, we’re debuting the feature via /std:c++latest mode and once we have all C++20 features implemented across all Visual Studio products (compiler, library, IntelliSense, build system, debugger, etc.), we’ll provide them through a new /std:c++20 mode. IntelliSense support is not currently available and our implementation doesn’t yet include recent changes in the ISO C++ standards meeting in Cologne.

What are C++ Concepts?

Concepts are predicates that you use to express a generic algorithm’s expectations on its template arguments.

Concepts allow you to formally document constraints on templates and have the compiler enforce them. As a bonus, you can also take advantage of that enforcement to improve the compile time of your program via concept-based overloading.

There are many useful resources about Concepts on the Internet. For example, isocpp has many blog posts about Concepts which include one from Bjarne Stroustrup.

What is supported?

The compiler support includes:

The compiler support doesn’t include recent changes in the ISO C++ standards meeting in Cologne.

The library support includes: <concepts>

Examples

Here are some examples on how Concepts can help you write more concise code. They also take less time to compile.

#include <concepts> // This concept tests whether 'T::type' is a valid type template<typename T> concept has_type_member = requires { typename T::type; }; struct S1 {}; struct S2 { using type = int; }; static_assert(!has_type_member<S1>); static_assert(has_type_member<S2>); // Currently, MSVC doesn't support requires-expressions everywhere; they only work in concept definitions and in requires-clauses //template <class T> constexpr bool has_type_member_f(T) { return requires{ typename T::type; }; } template <class T> constexpr bool has_type_member_f(T) { return has_type_member<T>; } static_assert(!has_type_member_f(S1{})); static_assert(has_type_member_f(S2{})); // This concept tests whether 'T::value' is a valid expression which can be implicitly converted to bool // 'std::convertible_to' is a concept defined in <concepts> template<typename T> concept has_bool_value_member = requires { { T::value } -> std::convertible_to<bool>; }; struct S3 {}; struct S4 { static constexpr bool value = true; }; struct S5 { static constexpr S3 value{}; }; static_assert(!has_bool_value_member<S3>); static_assert(has_bool_value_member<S4>); static_assert(!has_bool_value_member<S5>); // The function is only a viable candidate if 'T::value' is a valid expression which can be implicitly converted to bool template<has_bool_value_member T> bool get_value() { return T::value; } // This concept tests whether 't + u' is a valid expression template<typename T, typename U> concept can_add = requires(T t, U u) { t + u; }; // The function is only a viable candidate if 't + u' is a valid expression template<typename T, typename U> requires can_add<T, U> auto add(T t, U u) { return t + u; }

What about ranges?

We are also working on ranges. It provides components for dealing with ranges of element and has a tight relationship with Concepts.

In the meantime, we used the reference implementation range-v3 and cmcstl2 to test the Concepts support and they helped discover many issues. Some are related to the Concepts implementation and some are issues in other feature areas which are exposed by the new coding pattern enabled by Concepts. We fixed all issues in the first category and fixed most of the issues in the second category (the remaining issues are worked around in the source). We now compile and run all the tests in these libraries during our CI (continuous integration).

The testing also helped expose some source issues in the reference implementation and we reported them to the library owner.

Looking for libraries using C++20 features

Like many other new features we implemented recently, Concepts also use the new parser and semantics analysis actions. While they have a pretty good coverage and we have confidence in the quality, experience shows that we still sometimes see issues especially when people start to adopt new coding patterns enabled by the new features.

We are always looking for libraries which have heavy usage of new features. If you have some libraries which use Concepts or other C++20 features, please let us know and we are willing to add them to our daily RWC (real world code) testing. This will help us improve our compiler.

Talk to us!

If you have feedback on the C++20 Concepts support in Visual Studio, we would love to hear from you. We can be reached via the comments below. You can also use the Report a Problem tool in Visual Studio or head over to Visual Studio Developer Community. You can also find us on Twitter @VisualC.