【问题标题】:Use a template parameter in a preprocessor directive?在预处理器指令中使用模板参数?
【发布时间】:2011-02-23 15:58:45
【问题描述】:

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

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

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

        // some code here

        #endif
    }
};

当我尝试使用 Blah&lt;Foo&lt;0xFFFF&gt;&gt; 之类的东西时,VC++ 2010 抱怨我们尝试使用 #if 的行中括号不匹配。我猜预处理器对模板一无所知,而这种事情不在它的领域。说啥?

【问题讨论】:

  • 请注意:Blah&lt;Foo&lt;0xFFFF&gt;&gt; 不会在当前 c++ 中解析,您需要在 &gt;s 之间留一个空格。 Blah&lt;Foo&lt;0xFFFF&gt; &gt;.
  • 实际上,在 VC++ 2010 中它确实可以编译! :) 他们在 VC++ 2010 中部分实现了 C++0x。

标签: c++ templates c-preprocessor preprocessor-directive


【解决方案1】:

不,这是不可能的。预处理器非常愚蠢,它不知道程序的结构。如果T::Doo 没有在预处理器中定义(因为::,它不能定义),它不能评估那个表达式并且会失败。

但是,您可以依靠编译器为您做聪明的事情:

        if (T::Doo & 0x010) {
            // some code here
        }

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

【讨论】:

  • 如果Doo 不存在于T 中,这不会编译失败吗?
  • 谢谢。那正是我所想。然而,使用编译器对我来说并不理想,因为T 中可用的成员取决于T::DOO 中设置的位。我确信我以错误的方式处理这个问题。我会想出别的办法。但只是好奇我们可以用预处理器走多远。另一种选择可能是看看是否可以使用模板元编程技巧。
  • 他们可能可以。如果您提出一个新问题,其中包含您想要完成的详细信息,我们可以看看。
【解决方案2】:

T 中可用的成员取决于T::DOO 中设置的位

在我看来,T::DOO 就像一个子类标识符。所以我认为你的Foo 和相关类应该是保证DOO 被定义的类的子类。

关键是:为什么一定要使用位域?

【讨论】:

  • 这个问题的答案有点复杂,但你是对的。我正在使用这个 API (DirectX),它允许在指定如何格式化作为输入传递给其方法之一的某个结构的内容时具有一定的灵活性。有关如何进行结构设置的信息通过位字段传递。在我的应用程序中,我有两个抽象——第一个是一个模板类,它使用位域生成这个结构的实例集合,结构本身作为模板参数传递,另一个使用这个集合。评论续。下面
  • 我想在消费者类中编写一些条件代码,通过检查在位域中设置了哪些位来利用该结构的特定成员。呸!我不确定这有多大意义!由于源类的各种模板实例映射到结构的不同变体,因此必须有条件地编译相关代码 - 因此尝试查看是否可以使用预处理器的想法。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 2012-03-05
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    相关资源
    最近更新 更多