Last active
June 10, 2018 06:29
-
-
Save JadeMatrix/1f01dacc650f233165a0d3eead3a5098 to your computer and use it in GitHub Desktop.
libpqxx tablewriter tuple support proof-of-concept
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <type_traits> // std::enable_if | |
#include <utility> // std::size_t | |
#include <tuple> // std::tuple_size, std::get | |
#include <vector> | |
using std::to_string; | |
std::string to_string( const char* c ) { return std::string{ c }; } | |
std::string to_string( bool b ) { return b ? "true" : "false"; } | |
const std::string& to_string( const std::string& s ) { return s; } | |
namespace pqxx | |
{ | |
template<typename ITER, typename ACCESS> inline | |
std::string separated_list( //[t00] | |
const std::string &sep, | |
ITER begin, | |
ITER end, | |
ACCESS access) | |
{ | |
std::string result; | |
if (begin != end) | |
{ | |
result = to_string(access(begin)); | |
for (++begin; begin != end; ++begin) | |
{ | |
result += sep; | |
result += to_string(access(begin)); | |
} | |
} | |
return result; | |
} | |
template<typename ITER> inline std::string | |
separated_list(const std::string &sep, ITER begin, ITER end) //[t00] | |
{ return separated_list(sep, begin, end, [](ITER i){ return *i; }); } | |
template< typename CONTAINER > inline auto | |
// > inline std::string | |
separated_list(const std::string &sep, const CONTAINER &c) //[t10] | |
-> typename std::enable_if< | |
( | |
!std::is_void<decltype(begin(c))>::value | |
&& !std::is_void<decltype(end(c))>::value | |
), | |
std::string | |
>::type | |
// { return separated_list(sep, c.begin(), c.end()); } | |
{ return separated_list(sep, begin(c), end(c)); } | |
template< | |
typename CONTAINER, | |
typename ACCESS | |
> inline auto | |
separated_list(const std::string &sep, const CONTAINER &c, ACCESS access) | |
-> typename std::enable_if< | |
( | |
!std::is_void<decltype(begin(c))>::value | |
&& !std::is_void<decltype(end(c))>::value | |
), | |
std::string | |
>::type | |
{ | |
return separated_list(sep, begin(c), end(c), access); | |
} | |
struct passthrough_access | |
{ | |
template<typename T> constexpr auto operator()( T t_p ) const | |
-> decltype( *t_p ) | |
{ | |
return *t_p; | |
} | |
}; | |
template< | |
typename TUPLE, | |
std::size_t INDEX = 0, | |
typename ACCESS, | |
typename std::enable_if< | |
(INDEX == std::tuple_size<TUPLE>::value-1), | |
int | |
>::type = 0 | |
> inline std::string | |
separated_list(const std::string &sep, const TUPLE &t, const ACCESS& access) | |
{ return to_string(access(&std::get<INDEX>(t))); } | |
template< | |
typename TUPLE, | |
std::size_t INDEX = 0, | |
typename ACCESS, | |
typename std::enable_if< | |
(INDEX < std::tuple_size<TUPLE>::value-1), | |
int | |
>::type = 0 | |
> inline std::string | |
separated_list(const std::string &sep, const TUPLE &t, const ACCESS& access) | |
{ | |
return to_string(access(&std::get<INDEX>(t))) | |
+ sep | |
+ separated_list<TUPLE, INDEX+1>(sep, t, access); | |
} | |
template< | |
typename TUPLE, | |
std::size_t INDEX = 0, | |
typename std::enable_if< | |
(INDEX <= std::tuple_size<TUPLE>::value), | |
int | |
>::type = 0 | |
> inline std::string | |
separated_list(const std::string &sep, const TUPLE &t) | |
// { return to_string(std::get<INDEX>(t)); } | |
{ return separated_list(sep, t, passthrough_access{}); } | |
} | |
template< typename T > std::string escape_any( | |
const T& v, | |
const std::string& nullval | |
) | |
{ | |
return std::string{ "esc:\"" } + to_string( v ) + "\""; | |
} | |
class Escaper | |
{ | |
const std::string &m_null; | |
public: | |
explicit Escaper(const std::string &null) : m_null(null) {} | |
template<typename IT> std::string operator()(IT i) const | |
{ | |
return escape_any(*i, m_null); | |
} | |
}; | |
int main( int argc, char* argv[] ) | |
{ | |
auto ilist = { 1, 421, 51 }; | |
std::string string_array[] = { "hello", "world" }; | |
std::cout | |
<< pqxx::separated_list( ", ", std::make_tuple( 1, "hello", true, 13.75f ) ) | |
<< std::endl | |
<< pqxx::separated_list( ", ", std::make_tuple( 52345 ) ) | |
<< std::endl | |
<< pqxx::separated_list( ", ", ilist ) | |
<< std::endl | |
<< pqxx::separated_list( ", ", std::vector< int >{ ilist } ) | |
<< std::endl | |
<< pqxx::separated_list( ", ", string_array ) | |
<< std::endl | |
<< pqxx::separated_list( ", ", ilist, Escaper( "nullstr" ) ) | |
<< std::endl | |
<< pqxx::separated_list( ", ", std::make_tuple( 1, "hello", true, 13.75f ), Escaper( "nullstr" ) ) | |
<< std::endl | |
; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment