June 10th, 2019

How can I determine in a C++ header file whether C++/CX is enabled? How about C++/WinRT?

Suppose you’re writing a header file that wants to take advantage of C++/CX or C++/WinRT features if the corresponding functionality is available.

// async_event_helpers.h

#if (? what goes here ?)

// RAII type to ensure that a C++/CX deferral is completed.

template<typename T>
struct ensure_complete
{
   ensure_complete(T^ deferral) : m_deferral(deferral) { }
   ~ensure_complete() { if (m_deferral) m_deferral->Complete(); }

  ensure_complete(ensure_complete const&) = delete;
  ensure_complete& operator=(ensure_complete const&) = delete;

  ensure_complete(ensure_complete&& other)
  : m_deferral(std::exchange(other.m_deferral, {})) { }
  ensure_complete& operator=(ensure_complete&& other)
  { m_deferral = std::exchange(other.m_deferral, {}); return *this; }

private:
   T^ m_deferral;
};
#endif

#if (? what goes here?)

// RAII type to ensure that a C++/WinRT deferral is completed.

template<typename T>
struct ensure_complete
{
   ensure_complete(T const& deferral) : m_deferral(deferral) { }
   ~ensure_complete() { if (m_deferral) m_deferral.Complete(); }

  ensure_complete(ensure_complete const&) = delete;
  ensure_complete& operator=(ensure_complete const&) = delete;

  ensure_complete(ensure_complete&&) = default;
  ensure_complete& operator=(ensure_complete&&) = default;

private:
   T m_deferral{ nullptr };
};
#endif

What magic goes into the #if statement to enable the corresponding helpers only if the prerequisites have been met?

For C++/CX, the magic incantation is

#ifdef __cplusplus_winrt

If C++/CX is enabled, then the __cplusplus_winrt symbol is defined as the integer 201009, which is presumably a version number.

For C++/WinRT, the magic symbol is

#ifdef CPPWINRT_VERSION

This is defined to a string literal representing the version of C++/WinRT that is active. In addition to serving as a feature detector, this macro is used to ensure that all of the C++/WinRT header files you use are compatible with each other. (If not, you will get a compile-time assertion failure.)

The C++/WinRT team cautions that this is the only macro in the C++/WinRT header file that is supported for feature detection. Do not rely on the other WINRT_* macros in the C++/WinRT header files. They are implementation details and may change at any time.

 

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

3 comments

Discussion is closed. Login to edit/delete existing comments.

Newest
Newest
Popular
Oldest
  • W S

    Why is there not similar define for the SDK headers? Having to do #ifdef SOMESHELLFLAG is a nightmare to keep track of SDK versions and WINVER guards gets in the way.

    • Alex Cohn

      Because reliance on version number is not sustainable in the long run. When you check `__cplusplus_winrt`, don’t compare its value to 201009.

      • W S

        I agree in theory but you can’t check if a enum exists in a #if etc. __cplusplus_winrt is a number because we are going to compare against it. Presumably at some point we can do: #if __cplusplus_winrt >= 20420101 use featureX.

Feedback