簡體   English   中英

可擴展條件語句的機制

[英]Mechanism for extensible conditional statement

我的代碼中包含以下幾行:

//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 ++中的條件語句,該條件語句將自動考慮類A的帳戶聲明,因此它將具有其他行:

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預編譯。 可能嗎?

我只是創建一個函子向量:

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)

現在您可以將任何課程注冊為:

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

希望能有所幫助。

請參閱此在線演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM