问题
Is it possible to use a non-type constant template parameter in a preprocessor directive? Here's what I have in mind:
template <int DING>
struct Foo
{
enum { DOO = DING };
};
template <typename T>
struct Blah
{
void DoIt()
{
#if (T::DOO & 0x010)
// some code here
#endif
}
};
When I try this with something like Blah<Foo<0xFFFF>>
, VC++ 2010 complains something about unmatched parentheses in the line where we are trying to use #if
. I am guessing the preprocessor doesn't really know anything about templates and this sort of thing just isn't in its domain. What say?
回答1:
No, this is not possible. The preprocessor is pretty dumb, and it has no knowledge of the structure of your program. If T::Doo
is not defined in the preprocessor (and it can't be, because of the ::
), it cannot evaluate that expression and will fail.
However, you can rely on the compiler to do the smart thing for you:
if (T::Doo & 0x010) {
// some code here
}
Constant expressions and dead branches are optimized away even at the lower optimization settings, so you can safely do this without any runtime overhead.
回答2:
what members are available in T depends on which bits are set in
T::DOO
It sounds to me like T::DOO
is acting like a subclass identifier. So I'm thinking that your Foo
and related classes should be subclasses of a class that guarantees that DOO
is defined.
The key is: why must you use a bit field?
回答3:
Not sure if this applies to your situation, but it is possible to isolate different cases with template classes. For example: (using a modified version of your code from above)
template <typename T, int N>
struct Blah
{
void DoIt()
{
// normal DoIt() code
}
};
template <typename T>
struct Blah<T,5>
{
void DoIt()
{
// special DoIt() code for only when N==5
}
};
来源:https://stackoverflow.com/questions/2904376/use-a-template-parameter-in-a-preprocessor-directive