C ++ MACROS: условный код включает в выражение НЕ оператор

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

Это несколько надуманный пример, поскольку я попытался свести реальный код к более лаконичному примеру.

#include <map>
#include <iostream>
#include <functional>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/equal.hpp>

using FUNC = std::function<int(int,int)>;

#define BINDIF( method ) BOOST_PP_IF(1,std::bind(&B::method, this, std::placeholders::_1,std::placeholders::_2),nullptr)
//                                   ^ this needs to vary on value of the method param
//                                   ^ I tried BOOST_PP_EQUAL(nullptr, method) here
//                                     it concatenated several Boost macros and threw
//                                     an error about not recognizing the long symbol
//                                     it created

#define TABLE       \
T(Add, add)         \
T(Sub, sub)         \
T(Mul, mul)         \
T(Div, div)

#define T(k,v) k,
enum Ops: size_t {
TABLE
};
#undef T

class A {
public:
FUNC Func;
A(FUNC func)
: Func(func) {
}
};

class B {
std::map<Ops,A> As;
public:
int add(int x, int y) { return x + y; }
int sub(int x, int y) { return x - y; }
int mul(int x, int y) { return x * y; }
int div(int x, int y) { return x / y; }

B() {

#define T(k,v) std::make_pair(Ops::k, A( BINDIF(v) ) ),
As = {
TABLE
};
#undef T
}
};

int main() {
return 0;
}

Это правильно расширит код std :: bind, найденный в макросе BINDIF. Однако обратите внимание, что первый параметр, условный, установлен в 1. Если я изменяю это значение на 0, оно корректно сбрасывает значение nullptr. Проблема в том, что я хотел бы, чтобы это происходило при оценке параметра ‘method’, передаваемого в макрос BINDIF. Я хотел бы, чтобы значения nullptr были введены в таблицу, и поэтому код std :: bind не будет сгенерирован.

Я полностью осознаю, как выглядит этот пример, но в реальном коде, с которым я работаю, большинство столбцов содержат nullptr, так как я редко привязываюсь к одному из 4 указателей std :: function.

Вот расширение с 1:

><(((º> g++ -E -g -O0 -Wall -std=c++11 test.cpp

...removed for brevity

class B {
std::map<Ops,A> As;
public:
int add(int x, int y) { return x + y; }
int sub(int x, int y) { return x - y; }
int mul(int x, int y) { return x * y; }
int div(int x, int y) { return x / y; }

B() {As = {
std::make_pair(Ops::Add, A( std::bind(&B::add, this, std::placeholders::_1,std::placeholders::_2) ) ),
std::make_pair(Ops::Sub, A( std::bind(&B::sub, this, std::placeholders::_1,std::placeholders::_2) ) ),
std::make_pair(Ops::Mul, A( std::bind(&B::mul, this, std::placeholders::_1,std::placeholders::_2) ) ),
std::make_pair(Ops::Div, A( std::bind(&B::div, this, std::placeholders::_1,std::placeholders::_2) ) ),
};

}
};

int main() {
return 0;
}

Вот расширение с 0:

><(((º> g++ -E -g -O0 -Wall -std=c++11 test.cpp

...removed for brevity

class B {
std::map<Ops,A> As;
public:
int add(int x, int y) { return x + y; }
int sub(int x, int y) { return x - y; }
int mul(int x, int y) { return x * y; }
int div(int x, int y) { return x / y; }

B() {As = {
std::make_pair(Ops::Add, A( nullptr ) ),
std::make_pair(Ops::Sub, A( nullptr ) ),
std::make_pair(Ops::Mul, A( nullptr ) ),
std::make_pair(Ops::Div, A( nullptr ) ),
};

}
};

int main() {
return 0;
}

Пожалуйста, извините за любые опечатки и общую длину этого вопроса. Последние несколько дней я искал ответ здесь и в других местах и ​​не мог найти ничего, что могло бы сработать. Макро документация Boost довольно скудна.

Лол, конечно. Таблица с нулевым значением выглядит так:

#define TABLE       \
T(Add, add)         \
T(Sub, sub)         \
T(Mul, mul)         \
T(Div, nullptr)

В результате получился бы такой код:

As = {
std::make_pair(Ops::Add, A( std::bind(&B::add, this, std::placeholders::_1,std::placeholders::_2) ) ),
std::make_pair(Ops::Sub, A( std::bind(&B::sub, this, std::placeholders::_1,std::placeholders::_2) ) ),
std::make_pair(Ops::Mul, A( std::bind(&B::mul, this, std::placeholders::_1,std::placeholders::_2) ) ),
std::make_pair(Ops::Div, A( nullptr ) ),
};

-3

Решение

Хорошо, я думаю, что эта проблема неразрешима через MACROS. Я думаю, что на этом этапе понадобится мощь метапрограммирования шаблонов. Для тех, кто заинтересован, мне нужно в время компиляции либо passthru nullptr, либо связать с методом класса. Поиски продолжаются …

0

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


По вопросам рекламы [email protected]