Skip to content

Instantly share code, notes, and snippets.

@splinterofchaos
Created November 27, 2012 01:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save splinterofchaos/4151880 to your computer and use it in GitHub Desktop.
Save splinterofchaos/4151880 to your computer and use it in GitHub Desktop.
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
template< class F, class G > struct AccumRight {
F f = F();
G g = G();
constexpr AccumRight() { }
constexpr AccumRight( F f, G g)
: f(f), g(g) { }
template< class X, class Y >
constexpr auto operator () ( X&& x, Y&& y )
-> decltype( f(std::declval<X>(), g(std::declval<Y>()) ) )
{
return f( std::forward<X>(x), g(std::forward<Y>(y)) );
}
};
template< class F, class G, class A = AccumRight<F,G> >
constexpr A rAccumulation( F f, G g ) {
return A( f, g );
}
namespace free_fn {
template< class X, class Y >
constexpr auto add( X&& x, Y&& y )
-> decltype( std::declval<Y>() + std::declval<X>() )
{
return std::forward<X>(x) + std::forward<Y>(y);
}
template< class S >
int sum( const S& s ) {
using X = typename S::value_type;
return std::accumulate( s.begin(), s.end(), 0,
add<const X&,const X&> );
}
} // namespace free
namespace obj {
struct Add {
template< class X, class Y >
constexpr auto operator () ( X&& x, Y&& y )
-> decltype( std::declval<Y>() + std::declval<X>() )
{
return std::forward<X>(x) + std::forward<Y>(y);
}
};
constexpr auto add = Add();
struct Sum {
template< class S >
int operator () ( const S& s ) const {
using X = typename S::value_type;
return std::accumulate( s.begin(), s.end(), 0, add );
}
};
constexpr auto sum = Sum();
} // namespace obj
struct Selector {
int i;
Selector( int j=0 ) : i(j) { }
template< class S >
typename S::value_type operator () ( const S& s ) const {
return *std::next( s.begin(), i );
}
};
namespace std {
template< class X >
string to_string( const std::vector<X>& v ) {
string str = "[ ";
for( const X& x : v ) str += to_string(x) + " ";
str += "]";
return str;
}
// Because the standard doesn't define this.
string to_string( const std::string& s ) {
return s;
}
template< class T >
string to_string( const T& s ) {
ostringstream ss;
ss << s;
return ss.str();
}
} // namespace std
struct Printer {
std::string destination;
Printer( std::string filename )
: destination( std::move(filename) )
{
}
void redirect( std::string filename ) {
destination = std::move( filename );
}
template< class X >
void operator () ( const X& x ) {
std::ofstream s( destination, std::ios_base::app );
s << std::to_string(x);
}
};
#include <ctime>
struct StampedPrinter : Printer {
StampedPrinter( std::string filename )
: Printer( std::move(filename) )
{
}
template< class X >
void operator () ( const X& x ) {
std::time_t t = std::time( nullptr );
std::tm tm = *std::localtime( &t );
std::string time = std::to_string(tm.tm_min) + ":" +
std::to_string(tm.tm_sec) + " -- ";
Printer::operator()( time + std::to_string(x) + "\n" );
}
};
//template< class X >
//std::ostream& operator << ( std::ostream& os, const std::vector<X>& v ) {
// os << "[ ";
// for( const X& x : v ) os << x << ' ';
// os << ']';
// return os;
//}
int main() {
int sum;
std::vector<int> v = { 1, 2, 3, 4, 5 };
sum = std::accumulate( v.begin(), v.end(), 0, obj::add );
std::cout << "sum = " << sum << std::endl;
Selector nth( 0 );
std::cout << "first = " << nth(v) << std::endl;
nth.i = 2;
std::cout << "third = " << nth(v) << std::endl;
std::cout << "fourth = " << Selector(nth(v))(v) << std::endl;
std::vector<std::vector<int>> vv = { v, v, v };
sum = std::accumulate( vv.begin(), vv.end(), 0,
rAccumulation(obj::add,obj::sum) );
std::cout << "sum = " << sum << std::endl;
StampedPrinter prnt( "file1" );
prnt( v );
prnt.redirect( "file2" );
prnt( vv );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment