可扩展条件语句的机制
Mechanism for extensible conditional statement
我的代码中有这些行:
//lines in mycode.c++
QString str = "...some id...";
if( str == "int")
foo< int>()
else if( str == "QString")
foo< QString>()
...
我需要创建一种机制以在此条件语句中包含自定义类型。因此,任何程序员都可以注册他的 class 和 foo 模板函数的实现。
我是这样想象的:
//A.h -- custom class
class A { };
template< >
void foo< A>() { ... };
DECL( A, "A"); //macro to declare class
我想要 mycode.c++ 中的条件语句,它会自动考虑 class A[=32= 的声明], 所以它会有额外的行:
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-macros系统,或者Qt-precompilation。可能吗?
我只想创建一个函子向量:
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");
如果你真的愿意,我想你可以把它变成一个宏。
我会这样做:
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)
现在您可以将任何 class 注册为:
//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>();
希望对您有所帮助。
参见 this online demo。
我的代码中有这些行:
//lines in mycode.c++
QString str = "...some id...";
if( str == "int")
foo< int>()
else if( str == "QString")
foo< QString>()
...
我需要创建一种机制以在此条件语句中包含自定义类型。因此,任何程序员都可以注册他的 class 和 foo 模板函数的实现。
我是这样想象的:
//A.h -- custom class
class A { };
template< >
void foo< A>() { ... };
DECL( A, "A"); //macro to declare class
我想要 mycode.c++ 中的条件语句,它会自动考虑 class A[=32= 的声明], 所以它会有额外的行:
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-macros系统,或者Qt-precompilation。可能吗?
我只想创建一个函子向量:
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");
如果你真的愿意,我想你可以把它变成一个宏。
我会这样做:
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)
现在您可以将任何 class 注册为:
//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>();
希望对您有所帮助。
参见 this online demo。