Механизм расширяемого условного выражения

У меня есть эти строки в моем коде:

//lines in mycode.c++
QString str = "...some id...";

if( str == "int")
foo< int>()
else if( str == "QString")
foo< QString>()
...

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

Я представляю это так:

//A.h -- custom class
class A { };

template< >
void foo< A>() { ... };

DECL( A, "A"); //macro to declare class

Я хочу условное утверждение в mycode.c ++ это будет автоматически принимать во внимание объявление класса , поэтому у него будут дополнительные строки:

else if( str == "A")
foo< A>()

Я мог бы иметь такой эффект, как это:

//common.h
void process_id( QString str) {
if( str == "int")
foo< int>()
else if( str == "QString")
foo< QString>()
...
else if( str == "A") //this lines programmer put manually
foo< A>();
}

//mycode.c++
#include "common.h"
QString str = "some_id";

process_id( str);

но что если программист забудет отредактировать common.h файл?

Я подумал, может быть, использовать систему C-макросов или как-то Qt-прекомпиляцию. Является ли это возможным?

1

Решение

Я бы сделал что-то вроде этого:

void process_id(QString const & str)
{
auto it =  g_actions.find(str);
if ( it != g_actions.end() )
(it->second)(); //invoke action
}

И рамки для поддержки вышеперечисленного реализованы в виде:

 using action_t = std::function<void()>;

std::map<QString, action_t>  g_actions; //map of actions!

#define VAR_NAME(x)       _ ## x
#define DEFINE_VAR(x)  VAR_NAME(x)
#define REGISTER(type) char DEFINE_VAR(__LINE__) = (g_actions[#type] = &foo<type>,0)

Теперь вы можете зарегистрировать любой класс как:

 //these lines can be at namespace level as well!
REGISTER(A);
REGISTER(B);
REGISTER(C);

А потом позвони process_id() как:

process_id("A"); //invoke foo<A>();
process_id("B"); //invoke foo<B>();

Надеюсь, это поможет.

Увидеть это онлайн демо.

3

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

Я бы просто создал вектор функторов:

using ProcessFunc = std::function<bool(const QString&)>;
std::vector<ProcessFunc> ids;

void process_id(QString str) {
for (ProcessFunc& f : ids) {
if (f(str)) {
break;
}
}

// or...
std::any_of(ids.begin(), ids.end(), [&](const ProcessFunc& f){
return f(str);
});
}

Где вы просто предоставляете метод для добавления нового такого ProcessFunc:

template <typename T>
void register_class(const QString& name) {
ids.emplace_back([=](const QString& str) {
if (str == name) {
foo<T>();
return true;
}
else {
return false;
}
});
}

Ваш пример конкретно будет:

register_class<int>("int");
register_class<QString>("QString");
register_class<A>("A");

Что, я полагаю, вы могли бы превратить в макрос, если бы вы действительно этого хотели.

3

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