Skip to content

Instantly share code, notes, and snippets.

@amin-jabri
Forked from splinterofchaos/main.cpp
Created October 19, 2015 10:20
Show Gist options
  • Save amin-jabri/9de8b64e516fe59d22ed to your computer and use it in GitHub Desktop.
Save amin-jabri/9de8b64e516fe59d22ed to your computer and use it in GitHub Desktop.
clang 3.4 tests
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <string>
#include <cmath>
#include <future>
// Generalized constexprs allow multiple statements and loops!
template<typename X, size_t N>
constexpr unsigned int sum( X(&arr)[N] ) {
unsigned int s = 0;
for( int x=0; x < N; x++ )
s += arr[x]; // Mutation.
return s;
}
// And, they allow branching.
constexpr auto fact( unsigned long long x ) {
if( x <= 1 )
return 1ull;
else
return x * fact(x-1);
}
constexpr auto fact2( unsigned long long x ) {
auto product = x;
while( --x )
product *= x;
return product;
}
// Auto return type deduction.
// No need for decltype(t+u).
template<typename T, typename U=T>
auto add(T t, U u) { return t + u; }
// We can return lambdas this way!
template<typename T>
auto add_(T x) {
return [x](T y){ return add(x,y); };
}
[[deprecated]] std::vector<int> add_n(std::vector<int> v, unsigned int n) {
std::transform (
std::cbegin(v), std::cend(v),
std::begin(v),
add_(n) // Same as [=](int x){ return x+n; }.
// Also, same as std::bind(add<int>,n,_1).
);
return std::move(v);
}
template<typename T=double>
constexpr T pi = T(3.1415926535897932385);
template<template<typename...> class Seq>
Seq<int> primes = { 1, 2, 3, 5, 7, 11, 13, 17, 19 };
template<>
constexpr float pi<int> = pi<float>;
template<typename T>
struct Circle {
T radius;
using value_type = T;
Circle(T r) : radius(r) {}
Circle(const Circle& c) : radius(c.radius) {}
};
auto area = []( auto c ) {
using T = typename decltype(c)::value_type;
return pi<T> * c.radius * c.radius;
};
template<typename T>
using f_type = T(*)(Circle<T>);
template<typename T>
f_type<T> area2 = []( Circle<T> c ) {
return pi<T> * c.radius * c.radius;
};
template<typename F, typename Tup, size_t ...I>
auto apply_tuple( F&& f, Tup&& t, std::index_sequence<I...> ) {
return std::forward<F>(f) (
std::get<I>( std::forward<Tup>(t) )...
);
}
// The auto keyword especially helps here.
template<typename F, typename Tup >
auto apply_tuple( F&& f, Tup&& t ) {
using T = std::decay_t<Tup>;
constexpr auto size = std::tuple_size<T>();
using indicies = std::make_index_sequence<size>;
return apply_tuple( std::forward<F>(f), t, indicies() );
}
#include <experimental/optional>
template<typename T>
using optional = std::experimental::optional<T>;
optional<float> square_root( float x ) {
return x > 0 ? std::sqrt(x) : optional<float>();
}
auto qroot( float a, float b, float c )
-> optional< std::tuple<float,float> >
{
// Optionals implicitly convert to bools.
if( auto root = square_root(b*b - 4*a*c) ) {
float x1 = -b + *root / (2*a);
float x2 = -b - *root / (2*a);
return {{ x1, x2 }}; // Like optional{tuple{}}.
}
return {}; // An empty optional.
}
namespace std {
template<typename T>
std::string to_string( const std::vector<T>& v ) {
std::string s = "[ ";
unsigned int i = 0;
for( ; i < v.size()-1; i++ )
s += to_string(v[i]) + ", ";
if( i > 0 )
s += to_string(v.back());
return s + " ]";
}
template<typename T>
std::string to_string( const std::list<T>& l ) {
std::string s;
auto b = std::begin(l);
auto e = std::end(l);
--e;
for( ; b != e; b++ )
s += to_string(*b) + " -> ";
if( b != std::end(l) )
s += to_string(l.back());
return s;
}
template<typename Tuple, size_t I >
std::string tuple_to_str( const Tuple& t, std::index_sequence<I> ) {
return std::to_string( std::get<I>(t) );
}
template<typename Tuple, size_t I, size_t I2, size_t...Is>
std::string tuple_to_str( const Tuple& t, std::index_sequence<I,I2,Is...> ) {
return std::to_string( std::get<I>(t) ) + ","
+ tuple_to_str(t, std::index_sequence<I2,Is...>() );
}
template<typename ...T>
std::string to_string( const std::tuple<T...>& t ) {
using Is = std::make_index_sequence<sizeof...(T)>;
return "(" + tuple_to_str(t,Is()) + ")";
}
template<typename T>
std::string to_string( const optional<T>& o ) {
return o ? "(Just " + to_string(*o) + ")" : "Nothing";
}
}
template<typename T>
auto convert = [](const auto& x) {
return T(x);
};
// Clang is missing std::is_same_t.
template<typename T, typename U>
constexpr bool is_same = std::is_same<T,U>::value;
template<typename T, typename U>
constexpr bool is_same2 = false;
template<typename T>
constexpr bool is_same2<T,T> = true;
template<int x>
int mod6 = [](int y){ return y % 6; }(x);
decltype(auto) ref(int& x) {
return x;
}
decltype(auto) copy(int x) {
return x;
}
int main() {
pi<float>;
pi<double>;
std::vector<int> nums{ 5, 6, 7, 2, 9, 1 };
auto count = [i=0]( auto seq ) mutable {
for( const auto& e : seq )
i++;
return i;
};
std::cout << "There are " << count(nums) << " numbers." << std::endl;
// std::less, greater, plus, etc. can be made polymorphic.
std::cout << "nums = " << std::to_string(nums) << std::endl;
std::sort( std::begin(nums), std::end(nums), std::less<>() );
std::cout << "nums sorted = " << std::to_string(nums) << std::endl;
std::sort( std::begin(nums), std::end(nums), std::greater<>() );
std::cout << "nums reversed = " << std::to_string(nums) << std::endl;
constexpr auto fact10 = fact(10);
std::cout << "The factorial of 10 equals " << fact10 << std::endl;
constexpr auto fact10_2 = fact2(10);
std::cout << "The factorial of 10 equals " << fact10_2 << std::endl;
std::vector<Circle<float>> circlesF{ 0, 2, 4 };
std::vector<Circle<double>> circlesD{ 6, 8, 9 };
// Instead of writing the same loop twice, use a lambda!
auto print_each_radius = []( const auto& list ) {
for( auto circle : list )
std::cout << "The area of a circle with radius="
<< circle.radius << " is " << area(circle) << std::endl;
};
print_each_radius( circlesF );
print_each_radius( circlesD );
std::cout << "If the radius is " << 10 << ", the area is "
<< area2<float>(10) << std::endl;
std::cout << "pi<float> is not pi<double> : "
<< std::boolalpha << (&pi<float> != &pi<int>) << std::endl;
std::cout << "10 mod 6 equals " << mod6<10> << std::endl;
std::cout << "First primes (vec) : "
<< std::to_string( primes<std::vector> ) << std::endl;
std::cout << "First primes (list) : "
<< std::to_string( primes<std::list> ) << std::endl;
constexpr int arr[] = {1,4,5};
constexpr int ans = sum(arr);
std::cout << "Sum of 1, 4, and 5 = " << ans << std::endl;
std::unique_ptr<int> p = std::make_unique<int>(5);
auto add_p = [p=std::move(p)](int x){ return x + *p; };
std::cout << "5 + 5 = " << add_p(5) << std::endl;
std::cout << "1'000'000 becomes " << 1'000'000 << std::endl;
std::cout << "1'0'0 becomes " << 1'0'0 << std::endl;
// Asyncronously get an int from the file named "info".
std::future<int> readInt = std::async (
std::launch::async,
[](){
auto file = fopen("info", "r");
char buf[10];
int value;
fgets( buf, sizeof buf, file );
sscanf( buf, "%i", &value );
return value;
}
);
std::future<int> add_five = std::async (
std::launch::async,
[readInt = std::move(readInt)]() mutable {
return readInt.get() + 5;
}
);
std::cout << "Let p=5. 5 + p = " << add_five.get() << std::endl;
std::tuple<long,int> tup{ 1'000'000'000, 100 };
// Tuples can be addressed by type.
std::cout << std::get<long>(tup) << " / " << std::get<int>(tup) << " = "
<< apply_tuple( std::divides<>(), tup ) << std::endl;
std::cout << "Adding an int and a long produces a long: ";
using AddResult = std::result_of_t< std::plus<>(int,long) >;
std::cout << std::boolalpha << is_same<long,AddResult> << std::endl;
auto roots = qroot(1,0,-4);
std::cout << "In x^2 - 4, x equals "
<< std::to_string(roots) << std::endl;
roots = qroot(1,0,4);
std::cout << "In x^2 - 4, x equals "
<< std::to_string(roots) << std::endl;
int refMe = 5;
std::cout << "refme = " << refMe << std::endl;
decltype(auto) a_ref = ref(refMe);
std::cout << "Change to 10 through reference." << std::endl;
a_ref = 10;
std::cout << "refme = " << refMe << std::endl;
int copyMe = 5;
std::cout << "copyme = " << copyMe << std::endl;
decltype(auto) copied = copy(copyMe);
std::cout << "Changed copy to 10." << std::endl;
copied = 10;
std::cout << "copyme = " << copyMe << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment