commit 6e4119a4997a88b471b821f89ecad05a2a0cc91d
Author: David Sorber <david.sorber@gmail.com>
Date:   Thu Jan 19 15:32:03 2017 -0500

    I finally got back to working on this POC, and I was able to get it mostly working. The only issue right now is that the template magic is attempting to create code for which the types don't match and don't cast decay nicely. That is if you try to assign a std::string to a tuple. Hopefully I can fix this with a bit of massaging.

diff --git a/software/sqlite_poc/DBManager.cc b/software/sqlite_poc/DBManager.cc
index b15c2d3..188c82c 100644
--- a/software/sqlite_poc/DBManager.cc
+++ b/software/sqlite_poc/DBManager.cc
@@ -12,26 +12,11 @@ DBManager::DBManager(const std::string& db_path)
     }
     else
     {
-        std::cout << "WORKED" << std::endl;
+        std::cout << "DB connected\n" << std::endl;
     }
-    
-    numba = 17;
-    
 }
 
 DBManager::~DBManager()
 {
     sqlite3_close(this->db);
 }
-
-void DBManager::test()
-{
-    std::cout << "Numba: " << numba << std::endl;
-}
-
-
-//~ template<typename T>
-//~ void DBManager::func(T foo)
-//~ {
-    //~ std::cout << "Does this work??? " << foo << std::endl;
-//~ }
diff --git a/software/sqlite_poc/DBManager.h b/software/sqlite_poc/DBManager.h
index 6494384..b9c699a 100644
--- a/software/sqlite_poc/DBManager.h
+++ b/software/sqlite_poc/DBManager.h
@@ -7,49 +7,47 @@
 
 #include <sqlite3.h> 
 
-template <size_t I>
-struct visit_impl
+template<size_t I>
+struct builder_impl
 {
-    template <typename T, typename V>
-    static void visit(T& tup, size_t idx, V value)
+    template<typename T, typename G>
+    static void set_value(T& tup, size_t idx, G& val)
     {
-        if (idx == I - 1) 
+        if (idx == I - 1)
         {
-            if (std::is_same<std::get<I - 1>(tup), value>)
-            {
-                std::get<I - 1>(tup) = value;
-            }
-            else
-            {
-                assert(false);
-            }
+            std::get<I - 1>(tup) = val;
         }
         else 
         {
-            visit_impl<I - 1>::visit(tup, idx, value);
+            builder_impl<I - 1>::set_value(tup, idx, val);
         }
     }
 };
  
 template <>
-struct visit_impl<0>
+struct builder_impl<0>
 {
-    template <typename T, typename V>
-    static void visit(T& tup, size_t idx, V fun) { assert(false); }
+    template<typename T, typename G>
+    static void set_value(T& tup, size_t idx, G& val) 
+    { 
+        assert(false); 
+    }
 };
+
+template <typename G, typename... Ts>
+void set_value_at(std::tuple<Ts...>& tup, size_t idx, G const& val)
+{
+    builder_impl<sizeof...(Ts)>::set_value(tup, idx, val);
+} 
  
-//~ template <typename V, typename... Ts>
-//~ void visit_at(std::tuple<Ts...> const& tup, size_t idx, V value)
-//~ {
-    //~ visit_impl<sizeof...(Ts)>::visit(tup, idx, value);
-//~ }
- 
-template <typename V, typename... Ts>
-void visit_at(std::tuple<Ts...>& tup, size_t idx, V value)
+template <typename G, typename... Ts>
+void set_value_at(std::tuple<Ts...>& tup, size_t idx, G& val)
 {
-    visit_impl<sizeof...(Ts)>::visit(tup, idx, value);
+    builder_impl<sizeof...(Ts)>::set_value(tup, idx, val);
 }
 
+
+
 class DBManager
 {
     public:
@@ -61,8 +59,8 @@ class DBManager
         ~DBManager();
         
         // execute query
-        template<typename T>
-        std::vector<T*>* execute_query(
+        template<typename... T>
+        std::vector<std::tuple<T...>*>* execute_query(
             const std::string& sql_statement,
             int& return_code)
         {
@@ -76,18 +74,14 @@ class DBManager
                 return nullptr;
             } 
             
-            auto output_vector = new std::vector<T*>();
-            
-            int step_return = 0;
+            auto output_vector = new std::vector<std::tuple<T...>*>();            
             
             // Iterate until we've collected all the output
-            do 
+            int step_return = 0;
+            while ((step_return = sqlite3_step(sqlite_statement)) != SQLITE_DONE)
             {
-                // Gran the
-                step_return = sqlite3_step(sqlite_statement);
-                
                 // Create a new result row to be populated below
-                auto result_row = new T();
+                auto result_row = new std::tuple<T...>();
                 
                 // Iterate over the columns in the row
                 int num_cols = sqlite3_data_count(sqlite_statement);
@@ -95,58 +89,39 @@ class DBManager
                 {
                     switch(sqlite3_column_type(sqlite_statement, col_idx))
                     {
-                        case SQLITE_INTEGER:
-                            visit_at(*result_row, col_idx, 
-                                     sqlite3_column_int64(sqlite_statement, col_idx));
-                        
-                            //~ std::get<col_idx>(result_row) = 
-                                //~ sqlite3_column_int64(sqlite_statement, col_idx);
+                        case SQLITE_INTEGER:                        
+                            set_value_at(*result_row, col_idx, 
+                                         sqlite3_column_int64(sqlite_statement, 
+                                                              col_idx));
                             break;
                             
                         case SQLITE_FLOAT:
-                            visit_at(*result_row, col_idx, sqlite3_column_double(sqlite_statement, col_idx));
-                            //~ std::get<col_idx>(result_row) = 
-                                //~ sqlite3_column_double(sqlite_statement, col_idx);
+                            set_value_at(*result_row, col_idx, 
+                                         sqlite3_column_double(sqlite_statement, 
+                                                                col_idx));
                             break;
                             
                         case SQLITE_TEXT:
-                            visit_at(*result_row, col_idx, 
-                                     std::string(reinterpret_cast<const char*>(sqlite3_column_text(sqlite_statement, col_idx))));
-                         
-                            //~ std::get<col_idx>(result_row) = 
-                                //~ std::string(sqlite3_column_text(sqlite_statement, col_idx));
+                            //~ set_value_at(*result_row, col_idx, 
+                                         //~ std::string(reinterpret_cast<const char*>(sqlite3_column_text(sqlite_statement, col_idx))));
                             break;
                             
                         case SQLITE_BLOB:
                             break;
                             
                         case SQLITE_NULL:
+                            //~ set_value_at(*result_row, col_idx, std::string(""));
                             break;
                     }
                 }
                 
-                
+                output_vector->push_back(result_row);
             }
-            while (step_return == SQLITE_ROW);
             
             return output_vector;
         }
         
-        void test();
- 
-        // templatized member function!
-        template<typename T>
-        std::vector<T> func(T& foo)
-        {
-            std::cout << "Does this work??? " << std::get<2>(foo) << std::endl;
-            
-            std::vector<T> bar;
-            bar.push_back(foo);
-            return bar;
-        }
-    
     private:
     
         sqlite3 *db;
-        uint32_t numba;
 };
diff --git a/software/sqlite_poc/main.cc b/software/sqlite_poc/main.cc
index 2956cfa..15a6edf 100644
--- a/software/sqlite_poc/main.cc
+++ b/software/sqlite_poc/main.cc
@@ -1,31 +1,65 @@
-
+#include <iomanip>
 #include <iostream>
 #include <tuple>
 
 #include "DBManager.h"
 
 
+// helper function to print a tuple of any size
+template<class Tuple, std::size_t N>
+struct TuplePrinter {
+    static void print(const Tuple& t) 
+    {
+        TuplePrinter<Tuple, N-1>::print(t);
+        std::cout << ", " << std::get<N-1>(t);
+    }
+};
+ 
+template<class Tuple>
+struct TuplePrinter<Tuple, 1> {
+    static void print(const Tuple& t) 
+    {
+        std::cout << std::get<0>(t);
+    }
+};
+ 
+template<class... Args>
+void print(const std::tuple<Args...>& t) 
+{
+    std::cout << "(";
+    TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
+    std::cout << ")\n";
+}
+
+
 int main(int argc, char** argv)
 {
     std::cout << "SQLite Proof of Concept Exerciser" << std::endl;
 
+    // Make a DBManager instance which will connect to our test DB automagically
     DBManager db_mgr("database.db");
-    db_mgr.test();
-    
-    //~ std::tuple<std::string, int, double> foo{"hello", 120, 3.14};
     
-    //~ db_mgr.func(foo);
     
-    //~ visit_at(foo, 1, 18);
-    
-    
-    std::string query("SELECT Number FROM sample;");
-    int rc(0);
-    
-    
-    auto results = db_mgr.execute_query<std::tuple<int64_t>>(query, rc);
+    // Make a query
+    std::string query("SELECT Number, Float FROM sample;");
     
+    // Execute the query making sure the template params match up with the
+    // query params
+    int rc = 0;    
+    auto results = db_mgr.execute_query<int64_t, double>(query, rc);
     std::cout << "Return code: " << rc << std::endl;
     
+    // If we returned successfully, print out the result rows
+    if (! rc)
+    {
+        uint32_t row_index = 0;
+        for (auto row : *results)
+        {
+            std::cout << "Row: " << std::setw(4) << row_index << " - ";
+            print(*row);
+            ++row_index;
+        }
+    }
+    
     return 0;
 }
