-
-
Save amin-jabri/9de8b64e516fe59d22ed to your computer and use it in GitHub Desktop.
clang 3.4 tests
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 <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