使用可变参数模板将嵌套类型列表转换为平面类型列表

时间:2014-12-10 13:33:38

标签: c++ metaprogramming variadic-templates typelist

以下代码可能是ORM实现的开始,但是我遇到了一些元编程方面的问题(没有惊喜)。下面的代码将是开发可以创建表(以及稍后读取和写入行)的类的开始。但我已经变得邪恶了#34;刽子手缩进"在主要的嵌套表声明(任何人想要链接xkcd漫画关于此???)。所以我想要的是使用可变参数模板参数包将嵌套格式更改为平面列表。

如何使用可变参数模板将main中的嵌套类型列表更改为平面列表?

#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;

1 个答案:

答案 0 :(得分: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