шаблоны — есть ли техника программирования на C ++, которая является приблизительным эквивалентом времени выполнения #ifdef?

Например, у меня есть вызов функции в некотором коде, который я хочу включить / отключить, как мне нравится.

Обычно я мог бы просто использовать if, но тогда он каждый раз проверял бы, можно ли запустить функцию, чего я не хочу. Я просто хочу, чтобы код никогда не делал эту проверку.

Блоки ifdef могут быть грязными и довольно грязными, они накапливаются и затрудняют чтение кода.

Разве я не могу решить это с помощью какого-то шаблона? Я знаю, что могу сделать несколько лямбд для создания каждой версии возможного вызова функции, который я хотел бы.

Это то, что означает статический, если? Потому что, на мой взгляд, я хочу сделать самоизменяющийся код, который я не знаю, хорошая ли это идея или вообще возможна.

1

Решение

Если я не понял ваш вопрос, я думаю, вы хотите что-то вроде Шаблон дизайна стратегии что для принятия решения во время выполнения.

Но только потому, что вы попросили шаблон, вот пример использования Основанное на политике метапрограммирование шаблона …
Но здесь решение принимается во время компиляции.

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

Другие решения

Предполагая, что это решение должно быть принято во время выполнения …

Хотя существует множество сложных решений этой проблемы, указатель на функцию — это простой метод (хотя я сомневаюсь, что его производительность значительно лучше, чем только условная).

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

Вы можете использовать функцию перегрузки и логический параметр шаблона:

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_type или же std::false_type в зависимости от того B это правда или ложь. Этот тип будет использоваться в разрешении перегрузки, поэтому компилятор выберет правильный метод для вас. Вы можете просто определить одну из функций как пустую. Это похоже на «отключение» вызова, когда B ложно, например.

Решение о том, какую функцию вызывать, делается во время компиляции, поэтому вы страдаете нет время выполнения для этого решения.

1

Да, есть способы сделать то, что вы хотите, но, поскольку они выполняются во время выполнения, они определяют стоимость. Относительно того, что я даю ниже, быстрее или медленнее, чем если … Вам придется профилировать и посмотреть. Вы платите за разыменование, но теряете лишнюю ветку.

Функциональные указатели

Вы можете решить эту проблему, имея несколько версий функций (или объектов с виртуальными функциями).

Пример:

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.");
}
1
По вопросам рекламы [email protected]