Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does WINAPI_FAMILY_PARTITION do?

Tags:

c++

windows

I am reading the definition of the header file winapifamily.h and notice the following definition of the WINAPI_FAMILY_PARTITION:

#define WINAPI_FAMILY_PARTITION(Partitions)     (Partitions)

And the general usage of the macro (as an example) is the following:

#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)

Now I am so confused, it seems that it is equivalent to

#if WINAPI_PARTITION_APP

What's the point of having the #if WINAPI_FAMILY_PARTITION(...) at all?

This is the relevant section of the winapifamily.h header file:

/*
 * Header files use the WINAPI_FAMILY_PARTITION macro to assign one or
 * more declarations to some group of partitions.  The macro chooses
 * whether the preprocessor will emit or omit a sequence of declarations
 * bracketed by an #if/#endif pair.  All header file references to the
 * WINAPI_PARTITION_* values should be in the form of occurrences of
 * WINAPI_FAMILY_PARTITION(...).
 *
 * For example, the following usage of WINAPI_FAMILY_PARTITION identifies
 * a sequence of declarations that are part of both the Windows Desktop
 * Partition and the Windows-Phone-Specific Store Partition:
 *
 *     #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP)
 *     ...
 *     #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP)
 *
 * The comment on the closing #endif allow tools as well as people to find the
 * matching #ifdef properly.
 *
 * Usages of WINAPI_FAMILY_PARTITION may be combined, when the partitition definitions are
 * related.  In particular one might use declarations like
 * 
 *     #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 *
 * or
 *
 *     #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
 *
 * Direct references to WINAPI_PARTITION_ values (eg #if !WINAPI_FAMILY_PARTITION_...)
 * should not be used.
 */ 
#define WINAPI_FAMILY_PARTITION(Partitions)     (Partitions)
like image 485
Yuchen Avatar asked Aug 14 '15 13:08

Yuchen


2 Answers

Suppose a file contain code which can be used in metro app
So the header will define

WINAPI_FAMILY = WINAPI_PARTITION_APP

=>WINAPI_FAMILY_DEKSTOP_APP has value of 2

#define WINAPI_FAMILY_PARTITION(Partition)  ((WINAPI_FAMILY & Partition) == Partition)

The macro will check what is type of API family

Now suppose u want write code that only works under metro environment, so

#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
    your code for metro application
#endif

Substituting values

WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) => ((2 & 2) == 2

Now if user wants to use for metro code they have to define

Why indirection required WINAPI_FAMILY = WINAPI_PARTITION_APP

3 = >  00 11     (both desktop & metro)
2 =>   00 10     (metro apis)
1  =>  00 01     (desktop)

this AND function macro is used, because if WINAPI_FAMILY is 3, means both apis can be used #define WINAPI_FAMILY_PARTITION(Partition), then u can specify Partition = 2, 3 and doing (3 & 1) or (3& 2) == 1 that means if WINAPI_FAMILY = 3, u can use both (desktop or metro apis) Thats why anding is required

like image 168
vito Avatar answered Sep 20 '22 03:09

vito


They're now defining an API which may support further intelligence in the future. E.g. they might define WINAPI_PARTITION_DESKTOP as (2 | WINAPI_PARTITION_DEPRECATED) in the future, and have WINAPI_FAMILY_PARTITION(x) check the WINAPI_PARTITION_DEPRECATED bit in x. This sort of future flexibility (for Microsoft) wouldn't be allowed if developers were allowed assume that WINAPI_PARTITION_DESKTOP would expand to a single Integer Constant Expression.

like image 29
MSalters Avatar answered Sep 21 '22 03:09

MSalters