1. class comparison in REQUIRE need operator == and toString/template specialization/insertion operator
2. CATCH_TRANSLATE_EXCEPTION customize ex.message
#define CATCH_CONFIG_MAIN in stdafx.h
#include "stdafx.h"
#include "c:\__tools\catch.hpp"
#include <ostream>
#include <exception>
class Book
{
public:
int Id;
bool operator==(const Book& b)
{
return b.Id == Id;
}
};
//std::ostream& operator<<(std::ostream& os, Book const& b)
// {
// os << "overloading OS";
// return os;
//};
namespace Catch {
template<> struct StringMaker<Book> {
static std::string convert(Book const& value)
{
return "String Maker Specialization";
}
};
//std::string toString(Book const& i)
//{
// return "to string for Book";
//}
}
class myException : public std::exception
{
public:
virtual const char* what() const throw()
{
return " my exception";
}
};
CATCH_TRANSLATE_EXCEPTION(myException& ex)
{
return ex.what();
}
TEST_CASE("This is a catch test","[Equal][LOG]")
{
Book b1, b2;
b1.Id = 90;
INFO("Start Testing");
REQUIRE(b1 == b2);
WARN("One assertion failed");
REQUIRE_FALSE(1 == 1);
}
TEST_CASE("This is another catch test","[CHK][EXP]")
{
CHECK_FALSE(1 == 1);
throw myException();
}
Tuesday, December 20, 2016
C++ Unit Test Framework Catch
Saturday, December 10, 2016
Compile Time Check IsNullable and IsReferenceType
public TimeSpan i { get; set; }
public TimeSpan? j { get; set; }
public string k { get; set; }
public Status? Status { get; set; }
public Data st1 { get; set; }
public Data? st2 { get; set; }
private void button_Click(object sender, RoutedEventArgs e)
{
bool b1 = IsNullable(i);
bool b2 = IsNullable(j);
bool b3 = IsNullable(k);
bool b4 = IsNullable(Status);
bool b5 = IsNullable(st1);
bool b6 = IsNullable(st2);
bool b7 = IsReferenceType(k);
}
static bool IsNullable<T>(T t) { return false; }
static bool IsNullable<T>(T? t) where T : struct { return true; }
static bool IsReferenceType<T>(T t) where T : class { return true; }
public enum Status
{
None,
Ok,
Error
}
public struct Data
{
}
Thursday, December 8, 2016
Shift Operator, ilog2 and test power of 2
(1) shift left of 1 generate all powers of 2.
(2) ilog2 is template specialization.
(3) shift 1 by ilog2(n) will get back n for power of 2 only
(4) compiler say too complex when using recursion for non-template function is_power_of_2
#include "stdafx.h"
#include <iostream>
using namespace std;
template <size_t X>
struct ilog2
{
enum {value=(1+ilog2<X/2>::value) };
};
template<>
struct ilog2<1> {enum {value=0}; };
template<size_t N>
bool is_pow_of_2()
{
return ((size_t)1 << ilog2<N>::value == N);
};
int main() {
cout << (1 << 3) << endl; // 8
cout << (1 << 9) << endl; // 512=2 power 9
cout << ((size_t)1 << ilog2<9>::value == 9) << endl;
cout << ((size_t)1 << ilog2<512>::value == 512) << endl;
cout << is_pow_of_2<9>() << endl;
cout << is_pow_of_2<512>() << endl;
return 0;
}
Wednesday, December 7, 2016
locking, lock free and wait free
locking --- lock_guard + mutex
lock free --- atomic + CAS
wait free --- atomic +fetch_add
ring buffer-- producer makes progress without any wait, so wait-free.
using namespace std;
typedef unsigned long ulong;
ulong _shared = 123UL;
int main() {
{
ulong* p=nullptr; //locking
*p = _shared;
mutex M;
{
lock_guard<mutex> l(M);
++(*p);
}
}
atomic<ulong>* p=0; //lock free
*p = _shared;
ulong xl = p->load(memory_order_relaxed);
while (!p->compare_exchange_strong(xl, xl + 1, std::memory_order_relaxed)) {}
p->fetch_add(1, memory_order_relaxed); //wait free
// cache line is 64 bytes, ul is 8 bytes, so thread>8=> sit on separate cache line, no sharing faster.
return 0;
}
lock_guard vs shared_lock is exclusive vs. shared in c++14
(1) C++ 14/17 rare write mostly read is Microsoft ReaderWriter Lock concept.
(2) lock_guard also aware of how many shared lock in effect before exclude locking so some overhead.
(3) shared_lock can try timed 1 ms to see if writing in progress and give up
(4) both lock_guard and shared_lock construct on the same shared_timed_mutex
std::map<std::string, std::string> _map;
std::shared_timed_mutex m;
std::string find_entry(std::string s)
{
std::shared_lock<std::shared_timed_mutex> guard(m);
auto it = _map.find(s);
if (it == _map.end())
{
throw runtime_error("not found");
}
return it->second;
}
void add_entry(std::string key,::string s)
{
std::lock_guard<std::shared_timed_mutex> guard(m);
_map.insert(make_pair(key,s));
}
void do_work_if_get_lock_in_1sec()
{
shared_lock<shared_timed_mutex> sl(m, std::chrono::seconds(1));
if (!sl.owns_lock())
return;
//do work after getting lock
}
Saturday, December 3, 2016
JSON Tester
#include "stdafx.h"
#include <iostream>
#include "JSONWrapper.hpp"
#include "render.hpp"
using namespace std;
int main() {
JSONWrapper jw, jw1, jw2;
//jw.value = true;
//jw.value = 123.45;
//jw.value = std::string{ "test" };
//jw.value = nullptr;
jw1.value = 678.90;
jw2.value = true;
JSONArray a{ jw1,jw2 };
JSONArray b{ jw1,jw2 };
//jw.value = a;
JSONObject obj;
obj.insert(std::pair<string, JSONArray>("k1", a));
obj["k2"] = b;
jw.value = obj;
cout << render_json_value(jw.value) << endl;
return 0;
}
fold.cpp recursion with compile time constant
(1) boost variant size =20, JSONValue variant=6
(2) v.which() = index
(3) using =typedef and decltype is to get typeinfo
(4) (n,N) recursion, Compile constant N=0, N+1 force n recurs 1 more time to get to n=N
(5) have not see example Max,Max get called
#pragma once
#include <string>
#include <boost\variant.hpp>
#include "render.hpp"
#include "get2.hpp"
using namespace std;
template<size_t N, size_t Max>
struct apply_at
{
template<typename R, typename T, typename F, typename...Fs>
static string apply(T&& t, size_t n, F&& f, Fs&&... fs)
{
if (n == N)
{
return forward<F>(f)(get2<N>(boost::forward<T>(t)));
}
else
{
return apply_at<N + 1, Max>::template apply<R, T, Fs...>(
boost::forward<T>(t),
n,
forward<Fs>(fs)...);
}
}
};
template<size_t Max>
struct apply_at<Max, Max>
{
template<typename R, typename T, typename...Fs>
static string apply(T, size_t, Fs...)
{
return R();
}
};
template<typename T,typename F, typename...Fs>
static string fold_at(T&& t, size_t n, F&& f, Fs&&... fs)
{
using R = decltype(f(get2<0>(t)));
return apply_at<0, sizeof...(Fs)+1>::template apply<R,T, F, Fs...>(
boost::forward<T>(t),
n,
forward<F>(f),
forward<Fs>(fs)...
);
};
template <typename... Ts, typename... Fs>
string fold(const boost::variant<Ts...>& v, Fs&&... fs)
{
// size boost::variant=60, JSONValue=6, so assert fail
//static_assert(sizeof...(Ts) == sizeof...(Fs), "# of fun and variant not matching.");
return fold_at(
v, v.which(), forward<Fs>(fs)...
);
};
6 function of JSON render matching 6 type in JSON variant
#pragma once
#include <string>
#include <sstream>
#include "JSONWrapper.hpp"
#include "join.hpp"
#include "fold.hpp"
#include <iomanip>
using namespace std;
string render_bool(bool b) { return b ? "true" : "false"; }
string render_double(double d) { return to_string(d); }
string render_null(nullptr_t) { return "null"; }
string render_string(const string& s)
{
stringstream ss;
ss << std::quoted(s);
return ss.str();
}
string render_json_value(const JSONValue& jsv);
string render_object(const JSONObject& obj)
{
return string{ "[" }+
join(obj.begin(), obj.end(), string{ "." },
[](const JSONObject::value_type& jsv) {
return render_string(jsv.first) + ":" + render_json_value(jsv.second);
}) + "]";
}
string render_array(const JSONArray& a)
{
return string{ "[" }+
join(a.begin(), a.end(), string{ "," },
[](const JSONValue& jsv) {
return render_json_value(jsv);
}) + "]";
}
string render_json_value(const JSONValue& jsv)
{
return fold(jsv,
render_bool, render_double, render_string,
render_null, render_array, render_object);
}
join.cpp on iterator though vector and map
#pragma once
#include "JSONWrapper.hpp"
#include <functional>
#include <string>
using namespace std;
string join(JSONObject::const_iterator first, JSONObject::const_iterator last, string delimitor,
std::function<string(const JSONObject::value_type&)> func)
{
string ret = "";
for (;first!= last; first++)
{
ret += func(*first) + delimitor;
}
return ret;
}
string join(JSONArray::const_iterator first, JSONArray::const_iterator last, string delimitor,
std::function<string(const JSONValue&)> func)
{
string ret = "";
for (;first!= last; first++)
{
ret += func(*first) + delimitor;
}
return ret;
}
Friday, December 2, 2016
get boost variant value using template specialization on literal value
It seems C++17 will have get<0> and get<N> but boost does not have that yet.
boost only have get<type> and which=0,1,2,3,4,5
The following specialization can hack get<N> for now
#pragma once
#include <boost\variant\get.hpp>
#include "JSONWrapper.hpp"
#include <string>
template<int N>
auto get2(JSONValue jsv);
template<>
auto get2<0>(JSONValue jsv)
{
return boost::get<bool>(jsv);
}
template<>
auto get2<1>(JSONValue jsv)
{
return boost::get<double>(jsv);
}
template<>
auto get2<2>(JSONValue jsv)
{
return boost::get<std::string>(jsv);
}
template<>
auto get2<3>(JSONValue jsv)
{
return boost::get<nullptr_t>(jsv);
}
template<>
auto get2<4>(JSONValue jsv)
{
return boost::get<JSONArray>(jsv);
}
template<>
auto get2<5>(JSONValue jsv)
{
return boost::get<JSONObject>(jsv);
}
boost variant defines JSON Wrapper
Note operator JSONValue&() const meant jw.operator const JSONValue&() the same as jw as in
cout<<render_json_value(jw)<<endl;
#include <vector>
#include <map>
#include <boost\variant.hpp>
typedef decltype(nullptr) nullptr_t;
struct JSONWrapper;
using JSONArray = std::vector<JSONWrapper>;
typedef std::map<std::string, JSONArray> JSONObject;
using JSONValue = boost::variant<bool, double, std::string, nullptr_t, JSONArray, JSONObject>;
struct JSONWrapper {
JSONValue value;
operator JSONValue&() { return value; }
operator const JSONValue&() const { return value; }
};
Subscribe to:
Comments (Atom)