如何让 C++ 预编译器做一个“循环”

Posted

技术标签:

【中文标题】如何让 C++ 预编译器做一个“循环”【英文标题】:How to make the C++ precompiler do a "loop" 【发布时间】:2012-12-03 04:22:25 【问题描述】:

我想简化以下代码:

switch (index)
    
    case 1:
        output = function1();
        break;
    case 2:
        output = function2();
        break;
    case 3:
        output = function3();
        break;
    ....

其中index 是编译时间常数。

如果我要使用预编译器宏,我需要使用它n 次,其中n 是案例数。如何将上述代码减少到 O(1) 行代码?

【问题讨论】:

为什么要这样做并降低代码的可读性? @EdHeal 我希望有一些预编译器的魔力可以使代码更具可读性。类似 output = SOME_MAGICAL_MACRO(function, index) @MartinDrozdik:使用宏不是很 C++-ish。请选择 Ed Heal 的答案。我首先建议检查代码。 (“Jinak se dá předávat 指针/参考 na funkci i jako 参数。Bývá 到 mnohem lepší。”) @Martin 谢谢你的建议。其实我是按照Ed的回答做的。有时,您别无选择,只能使用宏。例如,当您使用非 C++ 风格的库时。 @MartinDrozdik 哦,我明白了,那么别无选择:-) 【参考方案1】:

试试这个(假设函数 1-n 是真实姓名。正如你所说,该索引是编译时间常数):

#define CALLFUNCTION(x) function##x()

output = CALLFUNCTION(1);

更正:这不适用于变量,如果直接使用常量则可以。如果提供的代码是每个 case 语句中的全部,这可能会破坏目的。

根本不需要切换。或者,您可以使用模板专业化。

template<int index> function();

output = function<index>();    

并为每个索引专门化函数模板。

template<> function<1>()return 1; // or return function1();

如果它不是编译时间常数,则需要像 Fomin Arseniy 建议的那样生成开关。另一种选择是使用函数指针数组

【讨论】:

谢谢!一个问题是我无法更改 function1、...、functionn 的定义。 没问题,第一种方法可以正常工作,第二种方法可以是function1-functionn的包装器 编译器出错:'functionindex'没有依赖于模板参数的参数,因此'functionindex'的声明必须可用[-fpermissive] 你是对的,宏方法只有在索引替换为数字本身时才有效。抱歉没看到。【参考方案2】:

你不能用宏来做——但这会起作用(我认为):

int (*functions[])() =  &function1, &function2, &function3;

int output = functions[index]();

【讨论】:

【参考方案3】:

也许超级宏可以稍微简化你的工作。 只需使用代码创建“counter.def”文件:

COUNTER(1)
COUNTER(2)
COUNTER(3)
#undef COUNTER

然后在任何情况下使用 switch 或任何其他重复计数的结构

switch(index)

    #define COUNTER(i) case i: output = function##i(); break;
    #include "counter.def"

【讨论】:

哦不...请永远不要在 C++ 中这样做。

以上是关于如何让 C++ 预编译器做一个“循环”的主要内容,如果未能解决你的问题,请参考以下文章

C++ 预编译头文件已禁用

预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)

预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)

如何避免预编译头文件

VS2005 MFC 预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)

预编译(c++常问问题十二)