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)
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With