views:

134

answers:

3

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? Thanks!

+8  A: 

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.

Thomas
Won't this fail to compile if `Doo` is not present within `T`?
Kristo
Thanks. That's what I thought. Using the compiler is however not ideal for me because what members are available in `T` depends on which bits are set in `T::DOO`. I am sure I am approaching this the wrong way. I'll figure something else out. But was just curious about how far we can go with the preprocessor.Another option might be to see if template meta-programming tricks can be used for this.
Ranju V
They probably can. If you open a new question with the details of what you want to accomplish, we can have a look.
Thomas
+1  A: 

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?

Mike DeSimone
The answer to that is a bit involved but you're exactly right. I am working with this API (DirectX) which allows a certain amount of flexibility in specifying how you want to format the contents of a certain structure that is passed as input to one of its methods. Information on how you have the structure setup is passed via a bit-field. In my app I have 2 abstractions - the first is a template class that generates a collection of instances of this struct with the bit-field and the structure itself passed as template arguments and another which consumes this collection.Comment contd. below
Ranju V
I wanted to write some conditional code in the consumer class that made use of specific members of this structure by inspecting which bits are set in the bit-field. Phew! I am not sure how much of this made sense! Since there are various template instantiations of the source class mapped with different variants of the structure, the code in question must be conditionally compiled - hence the idea of trying to see if the preprocessor can be used.
Ranju V
A: 

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
    }
};
Chris