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

Avatar

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. 

15 comments

Comments are closed.

  • Avatar
    Андрей Попандопуло

    Today I’ve updated VS to 16.3.0 with Concepts support. There is no such a support (__cpp_lib_concepts isn’t defined). I’m using C++ Language Standard: Preview – Features from the Latest C++ Working Draft (/std:c++latest). Any thoughts?

    • Avatar
      Pal Balog

      in the recent 16.3.2 it is defined and the above example text works fine.

      static_assert(__cpp_lib_concepts == 201806L);

      In the preview it might only have the core.

      What does not yet work is intellisense, keywords concept is squiggled and so are concept names used in templates. Also the error message on broken concept violation have room to improve. But the feature is here indeed and we can start experimenting finally.

      • Avatar
        Sean Parent

        I have not been able to get concepts to work. I’m using the community edition, just updated to 16.3.3. I simply get “E0020 identifier “concept” is undefined” – I have /std::c++latest enabled. identifier __cpp_lib_concepts is undefined 🙁

        • Avatar
          Jakub SzymanskiMicrosoft logo

          Please update to 16.3.4, concepts did not work for me in 16.3.3
          f:\tmp\mm>call “c:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat”
          **********************************************************************
          ** Visual Studio 2019 Developer Command Prompt v16.3.4
          ** Copyright (c) 2019 Microsoft Corporation
          **********************************************************************
          [vcvarsall.bat] Environment initialized for: ‘x64’

          f:\tmp\mm>cl /Bv
          Microsoft (R) C/C++ Optimizing Compiler Version 19.23.28106.4 for x64
          Copyright (C) Microsoft Corporation. All rights reserved.

          Compiler Passes:
          c:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.23.28105\bin\HostX64\x64\cl.exe: Version 19.23.28106.4
          c:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.23.28105\bin\HostX64\x64\c1.dll: Version 19.23.28106.4
          c:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.23.28105\bin\HostX64\x64\c1xx.dll: Version 19.23.28106.4
          c:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.23.28105\bin\HostX64\x64\c2.dll: Version 19.23.28106.4
          c:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.23.28105\bin\HostX64\x64\link.exe: Version 14.23.28106.4
          c:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.23.28105\bin\HostX64\x64\mspdb140.dll: Version 14.23.28106.4
          c:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.23.28105\bin\HostX64\x64\1033\clui.dll: Version 19.23.28106.4

          f:\tmp\mm>more testconcepts.cpp

          #include
          #include

          // This concept tests whether ‘T::type’ is a valid type
          template
          concept has_type_member = requires { typename T::type; };

          struct S1 {};
          struct S2 { using type = int; };

          static_assert(!has_type_member);
          static_assert(has_type_member);

          int main()
          {
          std::cout <cl /EHsc /std:c++latest testconcepts.cpp
          Microsoft (R) C/C++ Optimizing Compiler Version 19.23.28106.4 for x64
          Copyright (C) Microsoft Corporation. All rights reserved.

          /std:c++latest is provided as a preview of language features from the latest C++
          working draft, and we’re eager to hear about bugs and suggestions for improvements.
          However, note that these features are provided as-is without support, and subject
          to changes or removal as the working draft evolves. See
          https://go.microsoft.com/fwlink/?linkid=2045807 for details.

          testconcepts.cpp
          Microsoft (R) Incremental Linker Version 14.23.28106.4
          Copyright (C) Microsoft Corporation. All rights reserved.

          /out:testconcepts.exe
          testconcepts.obj

          f:\tmp\mm>

  • Avatar
    Julian Watzinger

    How do I submit a library for use in RWC testing?

    I have a huge private library making use of the latest available features, and I regularly experience issues when upgrading to the latest version of MSVC, and I would like to contribute to Visual Studio as save myself some headache in the future 🙂

  • HGH
    HGH

    Are there any plans to support Clang on Windows? That would be very nice to have.

    #if defined(__clang__) && !defined(_SILENCE_CLANG_CONCEPTS_MESSAGE)
    #error Despite the presence of some Clang-related bits, this header currently does not support Clang. \
    You can define _SILENCE_CLANG_CONCEPTS_MESSAGE to silence this message and acknowledge that this is unsupported.
    #endif // defined(__clang__) && !defined(_SILENCE_CLANG_CONCEPTS_MESSAGE)

    I also am unable to compile anything with Clang 10 if C++ 20 is enabled.