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

Raymond Chen

Raymond

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.

 

Raymond Chen
Raymond Chen

Follow Raymond   

3 comments

Comments are closed.

  • W S
    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.

    • Avatar
      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
        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.