是否有一种C ++编程技术,大致相当于运行时#ifdef?

时间:2014-07-11 16:05:16

标签: c++ templates static-if

例如,我在某些代码中有一个函数调用,我希望能够根据需要启用/禁用。

通常我可以使用if,但是每次都会检查函数是否可以运行,这是我不想要的。我只是希望代码永远不会进行检查。

ifdef块可能很脏而且非常脏,它们堆积起来并使代码难以阅读。

我不能用某种模板解决这个问题吗?我知道我可以创建多个lambdas来构建我想要的每个版本的函数调用。

这是静态的,如果意味着什么?因为在我看来,我想要做的是自修改代码,我不知道这是一个好主意还是可能的。

4 个答案:

答案 0 :(得分:3)

假设需要在运行时做出这个决定......

虽然这个问题有很多复杂的解决方案,但函数指针是一种简单的方法(虽然我怀疑它的性能明显优于条件)。

#include <functional>
#include <iostream>

void option1(int) {
    std::cout << "option 1\n";
}

void option2(int) {
    std::cout << "option 2\n";
}

std::function<void(int)> fp(option1);

int main() {
    fp(3);

    // Let's change what fp does:
    fp = option2;
    fp(3);
}

答案 1 :(得分:2)

如果我没有误解你的问题,我认为你想要的是Strategy design pattern这样的运行时决定。

但仅仅因为您要求提供模板,以下是使用Policy based template metaprogramming...的示例 但是在这里,决定是在编译时做出的。

struct task {
    void do_task() { /* really do the task... */ }
};

struct no_task {
    void do_task() {} // empty
};

template<typename Task> class host : public Task {};

// here you take the decision...
// you can pass either task or no_task
host<task> h;

// and later you call the function...
h.do_task();

使用模板非常有效。
通过任何指向函数的指针都没有间接。
编译器很容易内联函数。
如果你传递no_task,呼叫站点甚至不会调用空函数(用你的编译器的优化级别来检查)。

答案 2 :(得分:1)

您可以使用函数重载和布尔模板参数:

template<bool B>
class X{
   // Function to be called when B is true
   void foo(std::true_type) {
      ..
   }
   // Function to be called when B is false
   void foo(std::false_type) {
        ... // leave empty to do nothing if B is false
   }



   void bar(){
      // This will call either of the foos depending on B
      foo(std::integral_constant<bool,B>());
   }

}

说明:类型特征std::integral_constant将评估为std::true_typestd::false_type类型的值,具体取决于B是真还是假。此类型将用于重载分辨率,因此编译器将为您选择正确的方法。您可以简单地将其中一个函数定义为空。这就像&#34;禁用&#34;例如,B为假时的呼叫。

决定调用哪个函数是在编译时完成的,因此您决定使用 no 运行时开销。

答案 3 :(得分:1)

是的,有办法做你想要的,但由于它们是运行时,它们确实推断出成本。至于我下面提供的内容是否比if更快或更慢...你将需要剖析并看到。你支付了取消引用费用,但却失去了额外的分支。

功能指针

您可以通过拥有多个版本的函数(或具有虚函数的对象)来解决此问题。

示例:

void stud(const char *) {}
void _log(const char *msg) { clog << msg << endl; };

void (*log)(const char *) = stud; 

void enable_logging()  { log = _log; }
void disable_logging() { log = stud; }

int main() {
    log("This will not be logged");
    enable_logging();
    log("This will be logged.");
}