読者です 読者をやめる 読者になる 読者になる

ゆとりーなの日記

日記的な事を書いて行くと思はれる

C++でSQLっぽいの

 って感じの煽りがあったので取り敢えず適当に作ってみました。

#include <iostream>
#include <string>
#include <boost/range/algorithm.hpp>
#include "sql.hpp"

struct id {};
struct name {};

int main() {
  auto table1 = aq::sql::create_table<aq::sql::field<id, int>, aq::sql::field<name, std::string>>();
  aq::sql::insert_into(table1, aq::sql::values(0, "hoge"));
  aq::sql::insert_into(table1, aq::sql::values(1, "huga"));
  aq::sql::insert_into(table1, aq::sql::values(2, "hage"));
  boost::for_each(aq::sql::select<name>::from(table1), [](const std::string &x) {
    std::cout << x << std::endl;
  });
  return 0;
}

 構文を何となく真似てみようというしてみましたが正直微妙な所です。

#ifndef AQ_SQL_HPP_
#define AQ_SQL_HPP_
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/include/copy.hpp>
#include <boost/fusion/include/find_if.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/range/algorithm.hpp>

namespace aq { namespace sql {
template <typename Name, typename T>
struct field {
  typedef Name name;
  typedef T type;
  
  field() = default;
  
  template <typename T_>
  field(T_ &&t) : value_(std::forward<T_>(t)) {}
  
  T get() const {
    return value_;
  };
  
 private:
  T value_;
};

template <typename... Fields>
std::vector<std::tuple<Fields...>> create_table() {
  return std::vector<std::tuple<Fields...>>();
}

namespace detail {
template <typename... Fields>
class values {
  struct to_field {
    template <typename T, typename U>
    T operator ()(const T &t, const U &u) {
      return T(u);
    }
  };
  
 public:
  explicit values(Fields... field) : data_(field...) {}
  
  template <typename T>
  T get_values() const {
    T t;
    boost::fusion::copy(data_, t);
    return t;
  }
  
 private:
  std::tuple<Fields...> data_;
};
}

template <typename... Fields>
detail::values<Fields...> values(Fields... field) {
  return detail::values<Fields...>(field...);
}

template <typename Table, typename Fields>
void insert_into(Table &table, Fields &&values) {
  table.push_back(values.template get_values<typename Table::value_type>());
}

template <typename Field>
class select {
  template <typename FindField>
  struct find_field_type {
    template <typename Field_>
    struct apply {
      typedef std::is_same<typename Field_::name, FindField> type;
    };
  };
  
 public:
  template <typename Table>
  static std::vector<typename boost::mpl::find_if<typename Table::value_type, find_field_type<Field>>::type::type::type> from(const Table &table) {
    std::vector<typename boost::mpl::find_if<typename Table::value_type, find_field_type<Field>>::type::type::type> v;
    boost::for_each(table, [&v](const typename Table::value_type &x) {
      v.push_back((*boost::fusion::find_if<find_field_type<Field>>(x)).get());
    });
    return v;
  }
};
}}

#endif

 取り敢えず現状の実装はこんな感じです。どっちかというと可変長テンプレートやりたかっただけって説もあります。あと未完にも程があります。はい。