Skip to content

Commit

Permalink
experimental impelementation of type traits and type deduction
Browse files Browse the repository at this point in the history
  • Loading branch information
patflick committed Aug 25, 2016
1 parent 39ce3cc commit 4c35839
Show file tree
Hide file tree
Showing 10 changed files with 1,018 additions and 6 deletions.
Binary file added experimental/a.out
Binary file not shown.
438 changes: 438 additions & 0 deletions experimental/flat_type.hpp

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions experimental/gcc_segfault.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <tuple>
#include <iostream>
#include <typeinfo>

template <typename... Types>
constexpr std::tuple<Types...> my_make_tuple(Types&&...t) {
return std::tuple<Types...>(std::forward<Types>(t)...);
}

struct st {
int i,j;
double d;
static constexpr auto x = my_make_tuple(&st::i,&st::j, &st::d);
};

int main() {
st t;

std::cout << typeid(st::x).name() << std::endl;

//int st::* x = std::get<0>(st::x);
}
99 changes: 99 additions & 0 deletions experimental/member_tuple.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Custom tuple implementation
*/

#ifndef MXX_MEMBER_TUPLE
#define MXX_MEMBER_TUPLE

#include <cstddef> // for size_t
#include <utility> // for std::forward

template <typename T>
struct type_wrap {
typedef T type;
};

template <size_t N, typename U>
struct member {
U m;

constexpr member() : m() {};
constexpr member(U&& u) : m(u) {};
constexpr member(const U& u) : m(u) {};

U& get() {
return m;
}
const U& get() const {
return m;
}
};

template <size_t I, typename... Types>
struct type_at;

template <typename Type>
struct type_at<0, Type> : type_wrap<Type> {};

template <typename Type, typename... Types>
struct type_at<0, Type, Types...> : type_wrap<Type> {};

template <size_t I, typename Type, typename... Types>
struct type_at<I, Type, Types...> : type_at<I-1, Types...> {};


// template sequence of size_t
template <size_t... S>
struct seq_ {};

template <size_t N, size_t I = 0, typename Seq = seq_<>>
struct seq;

template <size_t N, size_t I, size_t... Seq>
struct seq<N, I, seq_<Seq...>> : seq<N, I+1, seq_<Seq..., I>> {};

template <size_t N, size_t... Seq>
struct seq<N, N, seq_<Seq...>> : type_wrap<seq_<Seq...>> {};

template <typename Seq, typename... Types>
struct member_tuple_impl {};

// using flat multiple inheritance
// and unpacking of the sequence
template <size_t... Seq, typename... Types>
struct member_tuple_impl<seq_<Seq...>, Types...> : member<Seq, Types>... {
constexpr member_tuple_impl() : member<Seq, Types>()... {}
constexpr member_tuple_impl(Types&&...t) : member<Seq, Types>(std::forward<Types>(t))... {}
};

template <typename... Types>
struct member_tuple : member_tuple_impl<typename seq<sizeof...(Types)>::type, Types...> {

using base_type = member_tuple_impl<typename seq<sizeof...(Types)>::type, Types...>;

template <size_t I>
typename type_at<I, Types...>::type& get() {
return member<I, typename type_at<I, Types...>::type>::get();
}
template <size_t I>
const typename type_at<I, Types...>::type& get() const {
return member<I, typename type_at<I, Types...>::type>::get();
}

constexpr member_tuple() : base_type() {};
constexpr member_tuple(Types&&... t) : base_type(std::forward<Types>(t)...) {};
};

/*
template <typename... Types>
constexpr member_tuple<size_t, Types...> declare_type(Types&&... t) {
return member_tuple<size_t, Types...>(sizeof...(Types),std::forward<Types>(t)...);
};
*/

template <typename... Types>
constexpr std::tuple<Types...> declare_type(Types&&... t) {
return std::tuple<Types...>(std::forward<Types>(t)...);
};

#endif // MXX_MEMBER_TUPLE
136 changes: 136 additions & 0 deletions experimental/type_declarations.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@

#include <cstddef>
#include <iostream>
#include <utility>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <limits>

#include <mxx/comm.hpp>
#include <mxx/datatypes.hpp>

#include "type_traits.hpp"
#include "member_tuple.hpp"

struct no_member {
double d;
int i;
};

struct static_constexpr_obj {
int i;
double d;
//char x[4];

static constexpr auto datatype = declare_type(&static_constexpr_obj::i, &static_constexpr_obj::d);
};


struct static_const_obj {
double d;
int i;
typedef static_const_obj baz;
const static std::tuple<int baz::*, double baz::*> datatype;
};

struct nonstatic_obj {
int datatype;
};

struct nonstatic_func {
void datatype() {
}
};

struct static_func {
static void datatype() {}
};

struct multiple_funcs {
void datatype() { }
void datatype(int) { }
int datatype(int, int) { return 0;}
};

struct multiple_static_funcs {
static void datatype() { }
static void datatype(int) { }
static int datatype(int, int) { return 0;}
};

struct multi_mixed_funcs {
static void datatype() { }
static void datatype(float) { }
void datatype(int) { }
int datatype(int, int) { return 0;}
};


// check if this has a constexpr member (TODO use laptop version)

// is_simple_datatype<T>: if it declares its datatype and if all members are simple
// builtin types are simple by default

// need checker for has static object member (vs function)
// MXX_HAS_STATIC_OBJECT_MEMBER()

// buffer_tag, custom_buffer_tag, etc...

#define PRINT_TYPE_TRAIT(TRAIT, TYPE) std::cout << "" # TRAIT " for type " # TYPE ": " << TRAIT < TYPE > ::value << std::endl;

#define PRINT_TYPE_TRAIT_ALL(TRAIT) \
PRINT_TYPE_TRAIT(TRAIT, no_member) \
PRINT_TYPE_TRAIT(TRAIT, static_constexpr_obj) \
PRINT_TYPE_TRAIT(TRAIT, static_const_obj) \
PRINT_TYPE_TRAIT(TRAIT, nonstatic_obj) \
PRINT_TYPE_TRAIT(TRAIT, static_func) \
PRINT_TYPE_TRAIT(TRAIT, nonstatic_func) \
PRINT_TYPE_TRAIT(TRAIT, multiple_funcs) \
PRINT_TYPE_TRAIT(TRAIT, multiple_static_funcs) \
PRINT_TYPE_TRAIT(TRAIT, multi_mixed_funcs)

int main(int argc, char *argv[])
{
PRINT_TYPE_TRAIT_ALL(has_static_object_member)
PRINT_TYPE_TRAIT_ALL(has_static_function_member)

PRINT_TYPE_TRAIT_ALL(has_function_member)

// test for the overloaded functions:
std::cout << "has_function_member: void(): " << has_function_member<multiple_funcs, void()>::value << std::endl;
std::cout << "has_function_member: void(): " << has_function_member<multi_mixed_funcs, void()>::value << std::endl;
std::cout << "has_function_member: void(): " << has_function_member<multiple_static_funcs, void()>::value << std::endl;

std::cout << "has_static_function_member: void(): " << has_static_function_member<multiple_funcs, void()>::value << std::endl;
std::cout << "has_static_function_member: void(): " << has_static_function_member<multi_mixed_funcs, void()>::value << std::endl;
std::cout << "has_static_function_member: void(): " << has_static_function_member<multiple_static_funcs, void()>::value << std::endl;

std::cout << typeid(static_cast<void(multiple_funcs::*)()>(&multiple_funcs::datatype)).name() << std::endl;

std::cout << typeid(*static_cast<void(*)()>(multiple_static_funcs::datatype)).name() << std::endl;

//.PRINT_TYPE_TRAIT_ALL(has_datatype_constexpr)


/*
std::cout << typeid(decltype(foo::datatype)).name() << std::endl;
std::cout << "is const: " << std::is_const<decltype(foo::datatype)>::value << std::endl;
std::cout << "is const: " << std::is_const<decltype(baz::datatype)>::value << std::endl;
std::cout << "all are member: " << all_are<std::is_member_pointer, std::remove_const<decltype(foo::datatype)>::type>::value << std::endl;
std::cout << "all are member: " << all_are<std::is_member_pointer, std::tuple<int foo::*, double foo::*>>::value << std::endl;
std::cout << "all are member: " << are_all_member_pointer<decltype(baz::datatype)>::value << std::endl;
std::cout << "is member ptr: "<< std::is_member_pointer<std::tuple_element<0, decltype(foo::datatype)>::type>::value << std::endl;
std::cout << "is member ptr: "<< std::is_member_pointer<std::tuple_element<1, decltype(foo::datatype)>::type>::value << std::endl;
std::cout << "tuple size: " << std::tuple_size<decltype(foo::datatype)>::value << std::endl;
std::cout << " are all arith: " << all_are<std::is_arithmetic, std::tuple<int, float, char>>::value << std::endl;
*/

return 0;
}


114 changes: 114 additions & 0 deletions experimental/type_traits.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#ifndef MXX_EXPERIMENTAL_TYPE_TRAITS
#define MXX_EXPERIMENTAL_TYPE_TRAITS

#include <type_traits>
#include <tuple> // for all_are tuple specializations

#define MXX_DEFINE_HAS_STATIC_MEMBER_OBJECT(MEMBER_NAME) \
template <typename T, typename Enable = void> \
struct has_static_member_object_ ## MEMBER_NAME : std::false_type {}; \
\
template <typename T> \
struct has_static_member_object_ ## MEMBER_NAME <T, typename std::enable_if< \
!std::is_member_pointer<decltype(&T:: MEMBER_NAME )>::value \
&& !std::is_function<decltype(T :: MEMBER_NAME )>::value>::type> \
: std::true_type {}; \


#define MXX_DEFINE_HAS_MEMBER_OBJECT(MEMBER_NAME) \
template <typename T, typename Enable = void> \
struct has_member_object_ ## MEMBER_NAME : std::false_type {}; \
\
template <typename T> \
struct has_member_object_ ## MEMBER_NAME <T, typename std::enable_if< \
std::is_member_object_pointer<decltype(&T:: MEMBER_NAME )>::value>::type> \
: std::true_type {}; \
\

#define MXX_DEFINE_HAS_STATIC_MEMBER_FUNCTION(MEMBER_NAME) \
template <typename T, typename Sig = std::false_type, typename Enable = void> \
struct has_static_member_function_ ## MEMBER_NAME : std::false_type {}; \
\
template <typename T> \
struct has_static_member_function_ ## MEMBER_NAME \
<T, std::false_type, typename std::enable_if< \
std::is_function<decltype(T:: MEMBER_NAME )>::value>::type> \
: std::true_type {}; \
\
template <typename T, typename R, typename... Args> \
struct has_static_member_function_ ## MEMBER_NAME \
<T, R(Args...), typename std::enable_if< \
std::is_same<decltype(static_cast<R(*)(Args...)>(&T:: MEMBER_NAME )), \
R(*)(Args...)>::value>::type> \
: std::true_type {}; \

/*
template <typename T>
struct has_static_member : std::integral_constant<bool,
has_static_member_object<T>::value
|| has_static_member_function<T>::value> {};
*/

#define MXX_DEFINE_HAS_MEMBER_FUNCTION(MEMBER_NAME) \
template <typename T, typename Sig = std::false_type, typename Enable = void> \
struct has_member_function_ ## MEMBER_NAME : std::false_type {}; \
\
template <typename T> \
struct has_member_function_ ## MEMBER_NAME \
<T, std::false_type, typename std::enable_if< \
std::is_member_function_pointer<decltype(&T:: MEMBER_NAME )>::value>::type>\
: std::true_type {}; \
\
template <typename T, typename Func> \
struct has_member_function_ ## MEMBER_NAME <T, Func, typename std::enable_if< \
std::is_member_function_pointer< \
decltype(static_cast<Func T::*>(&T:: MEMBER_NAME ))>::value>::type> \
: std::true_type {}; \
\

#define MXX_DEFINE_MEMBER_TRAITS(MEMBER_NAME) \
MXX_DEFINE_HAS_MEMBER_OBJECT(MEMBER_NAME) \
MXX_DEFINE_HAS_STATIC_MEMBER_OBJECT(MEMBER_NAME) \
MXX_DEFINE_HAS_MEMBER_FUNCTION(MEMBER_NAME) \
MXX_DEFINE_HAS_STATIC_MEMBER_FUNCTION(MEMBER_NAME)

/*
template <typename T, typename Enable = void>
struct has_datatype_constexpr : std::false_type {};
template <typename T>
struct has_datatype_constexpr<T,typename std::enable_if<
std::is_member_object_pointer<typename std::tuple_element<0,decltype(T::datatype)>::type>::value
// the standard § 4.11 [conv.mem]:
// guarantuees that `valid` pointer-to-member are always distinct from the
// `null pointer to member`
&& std::get<0>(T::datatype) != nullptr
>::type> : std::true_type {};
*/

template <template <typename> class Trait, typename... Types>
struct all_are;

template <template<typename> class Trait, typename Type, typename... Types>
struct all_are<Trait, Type, Types...> : std::integral_constant<bool,
Trait<Type>::value && all_are<Trait, Types...>::value> {};

template <template<typename> class Trait, typename Type>
struct all_are<Trait, Type> : std::integral_constant<bool,
Trait<Type>::value> {};

// specialization for std::tuple
template <template<typename> class Trait, typename... Types>
struct all_are<Trait, std::tuple<Types...>> : std::integral_constant<bool,
all_are<Trait, Types...>::value> {};

template <typename... T>
struct are_all_member_pointer : std::false_type {};

template <typename... Types>
struct are_all_member_pointer<std::tuple<Types...>> : all_are<std::is_member_pointer, Types...> {};

template <typename... Types>
struct are_all_member_pointer<const std::tuple<Types...>> : all_are<std::is_member_pointer, Types...> {};

#endif // MXX_EXPERIMENTAL_TYPE_TRAITS
4 changes: 3 additions & 1 deletion include/mxx/benchmark.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,11 +484,13 @@ void bw_all2all_unaligned_char(const mxx::comm& c, const mxx::comm& smc, bool re
// time all2all
c.barrier();
auto start = std::chrono::steady_clock::now();
/*
if (realign) {
char_all2allv(&els[0], send_counts, &rcv[0], recv_counts, c);
} else {
*/
mxx::all2allv(&els[0], send_counts, &rcv[0], recv_counts, c);
}
//}
//mxx::datatype dt = mxx::get_datatype<char>();
//MPI_Alltoall(&els[0], m, dt.type(), &rcv[0], m, dt.type(), c);
auto end = std::chrono::steady_clock::now();
Expand Down
Loading

0 comments on commit 4c35839

Please sign in to comment.