在预处理指令中使用模板参数?

7

是否可以在预处理指令中使用非类型常量模板参数?以下是我的想法:

template <int DING>
struct Foo
{
    enum { DOO = DING };
};

template <typename T>
struct Blah
{
    void DoIt()
    {
        #if (T::DOO & 0x010)

        // some code here

        #endif
    }
};

当我尝试使用类似Blah<Foo<0xFFFF>>的东西时,VC++ 2010会抱怨我们在使用#if的那一行中有未匹配的括号。我猜预处理器实际上并不知道模板的任何内容,这种情况就不在它的领域内了。你怎么看?


只是需要注意一点:在当前的C++中,Blah<Foo<0xFFFF>>无法解析,你需要在>之间加上一个空格。Blah<Foo<0xFFFF> > - KitsuneYMG
实际上在 VC++ 2010 中可以编译! :) 它们在 VC++ 2010 中部分地实现了 C++0x。 - Raj
3个回答

11
不,这是不可能的。预处理器非常愚蠢,并且它没有程序结构的知识。如果T::Doo在预处理器中未定义(由于::),它将无法对该表达式进行求值并失败。
但是,您可以依赖编译器为您执行智能操作:
        if (T::Doo & 0x010) {
            // some code here
        }

即使在较低的优化设置下,常量表达式和死代码分支也会被优化掉,因此您可以安全地执行此操作,而无需任何运行时开销。


如果T中没有Doo,这段代码不会编译通过吧? - Michael Kristofik
谢谢。这正是我所想的。然而,对于我来说使用编译器并不理想,因为T中可用的成员取决于T::DOO中设置了哪些位。我相信我正在错误地处理这个问题。我会想出其他办法的。但我只是好奇我们可以用预处理器走多远。另一个选择可能是看看是否可以使用模板元编程技巧来解决这个问题。 - Raj
他们可能可以。如果您打开一个新问题并提供您想要实现的详细信息,我们可以看一下。 - Thomas

2

在T中可用的成员取决于T::DOO中设置了哪些位。

对我来说,T::DOO就像一个子类标识符。因此,我认为您的Foo和相关的类应该是一个类的子类,该类保证定义了DOO

关键在于:为什么必须使用位字段?


这个问题的答案有点复杂,但你说得完全正确。我正在使用这个API(DirectX),它允许在指定传递给其方法作为输入的某个结构的内容格式时具有一定的灵活性。有关如何设置结构的信息通过位域传递。在我的应用程序中,我有两个抽象——第一个是模板类,它生成通过模板参数传递的带有位域和结构本身的实例集合,另一个消耗此集合的类。 - Raj
我想在消费者类中编写一些条件代码,通过检查位域中设置的位来利用此结构的特定成员。哇!我不确定这有多少意义!由于源类的各种模板实例与结构的不同变体映射,所以相关的代码必须被有条件地编译 - 因此尝试使用预处理器的想法。 - Raj

1

不确定这是否适用于您的情况,但可以使用模板类来隔离不同的情况。例如:(使用上面修改过的代码的修改版本)

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接