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?
Explanation: A template parameter is a special kind of parameter that can be used to pass a type as argument.
Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.
A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
If there is just a single template parameter, I name it T (or U,V for nested templates). When there are multiple parameters and the use is not immediately obvious then I use descriptive names prefixed with T. For example, TKey, TValue, TIdentifiier, etc ...
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.
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?
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
}
};
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