2014-12-10 3 views
2

Следующий код может быть началом реализации ORM, но я застрял (никаких сюрпризов) в некоторых аспектах метапрограммирования. Нижеприведенный код будет началом разработки классов, которые могут создавать свои таблицы (а затем читать и писать их строки). Но я уже получаю злой «отжим палача» в этой вложенной табличной декларации в основном (любой хочет связать этот xkcd комикс об этом ???). Поэтому я хотел бы изменить этот вложенный формат на плоский список, используя пакет аргументов вариационного шаблона.Использование вариационного шаблона для преобразования вложенного списка типов в плоский список типов

Как изменить вложенный список вершин в основном на плоский список с использованием вариативных шаблонов?

#include <iostream> 
#include <string> 

using std::cout; 
using std::endl; 
using std::string; 

struct nil { 
    static const string create() {return string("");} 
}; 

struct required {}; 
struct optional {}; 

template <const char* nm,typename req=required> 
struct serial { 
    static const string create() {return string(nm)+" INTEGER PRIMARY KEY NOT NULL";} 
}; 

template <const char* nm,typename req=required> 
struct integer { 
    static const string create() {return string(nm)+" INTEGER NOT NULL";} 
}; 
template <const char* nm> 
struct integer<nm,optional> { 
    static const string create() {return string(nm)+" INTEGER";} 
}; 

template<typename car,typename cdr> 
struct cons { 
    static const string create() { 
     return 
      string("\t") 
      +car::create() 
      +",\n" 
      +cdr::create(); 
    } 
}; 

template<typename car> 
struct cons<car,nil> { 
    static const string create() { 
     return 
      string("\t")+car::create(); 
    } 
}; 

template<typename DDL> 
struct table { 
    static const string create() { 
     return 
      string("CREATE TABLE (\n") 
      +DDL::create() 
      +"\n);"; 
    } 
}; 

namespace fields { 
    const char id[]="id"; 
    const char someint[]="someint"; 
    const char someint2[]="someint2"; 
}; 

int main(int argc,char* argv[]) { 

    typedef table< 
     cons<serial<(const char*)fields::id>, 
      cons<integer<(const char*)fields::someint>, 
       cons<integer< 
        (const char*)fields::someint2,optional>,nil 
       > 
      > 
     > 
    > test; 

    cout << test::create() << endl; 

    return 0; 
} 

Вместо:

typedef table< 
     cons<serial<(const char*)fields::id>, 
      cons<integer<(const char*)fields::someint>, 
       cons<integer< 
        (const char*)fields::someint2,optional>,nil 
       > 
      > 
     > 
    > test; 

Я хотел бы быть в состоянии использовать:

typedef table< 
     list< 
      serial<(const char*)fields::id>, 
      integer<(const char*)fields::someint>, 
      integer<(const char*)fields::someint2,optional> 
     > 
    > test; 

ответ

2
template <typename... DDL> 
struct table { 
    static const string create() { 
     std::string s = "CREATE TABLE ("; 
     using expander = int[]; 
     (void)expander{0,(void(s += "\n\t" + DDL::create() + ","),0)...}; 
     if (sizeof...(DDL)) s.pop_back(); 
     s += "\n);"; 
     return s; 
    } 
}; 

Вход:

typedef table< 
      serial<(const char*)fields::id>, 
      integer<(const char*)fields::someint>, 
      integer<(const char*)fields::someint2,optional> 
     > test; 

Выход:

CREATE TABLE (
    id INTEGER PRIMARY KEY NOT NULL, 
    someint INTEGER NOT NULL, 
    someint2 INTEGER 
); 

DEMO

+0

есть способ для этого расширитель знать список его индекс? –

+0

@BrianJack да, используя 'index_sequence' –

+0

@BrianJack, где вам нужны те индексы, которые нужно разместить? –

 Смежные вопросы

  • Нет связанных вопросов^_^