简体   繁体   中英

Is there a C++ programming technique which is an approximate equivalent of a runtime #ifdef?

For example I have a function call in some code I want to be able to enable/disable as I like.

Normally I could just use an if, but then it would check each time if the function can be ran, which I don't want. I simply want the code to never do that check.

ifdef blocks can be messy and quite dirty, they pile up and make code hard to read.

Can't I solve this with some sort of template ? I know I can make multiple lambdas to build each version of the possible function call I'd want.

Is this what a static if means ? Because in my mind, what I want to do is a self modifying code, which I don't know if it's a good idea or possible at all.

Assuming that this decision needs to be made at runtime...

While there are plenty of complicated solutions to this problem, a function pointer is a simple method (although I doubt that it's performance is significantly better than just the conditional).

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

If I have not misunderstood your question, I think you want something like the Strategy design pattern which is for runtime decision.

But just because you asked for a template, here is an example using Policy based template metaprogramming... But here, the decision is taken at compile time.

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();

Using templates is really efficient.
There is no indirection through any pointer to function.
It is easy for compilers to inline the function.
If you pass it no_task , the call site won't even have a call to the empty function(check that out with your compiler's optimization levels).

You can use function overloading and a boolean template parameter:

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

}

Explanation: The type trait std::integral_constant will either evaluate to a value of type std::true_type or std::false_type depending on whether B is true or false. This type will be used in overload resolution so the compiler will pick the right method for you. You can simply define one of the functions to be empty. This is like "disabling" the call when B is false, for example.

The decision which function to call is done at compile time, so you suffer no runtime overhead for this decision.

Yes, there are ways to do what you want, but as they are runtime, they do infer a cost. As to whether what I give below is faster or slower than an if... You will have to profile and see. You pay for the dereference, but lose the extra branch.

Function pointers

You could solve this by having multiple versions of functions (or objects with virtual functions).

Example:

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.");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM