#pragma once
#ifndef TCG_TRAITS_H
#define TCG_TRAITS_H
// tcg includes
#include "sfinae.h"
// STD includes
#include <iterator>
//--------------------------------------------------------------------------
namespace tcg
{
//****************************************************************************
// TCG traits for generic type concepts
//****************************************************************************
template <typename T>
struct traits {
typedef T *pointer_type;
typedef T pointed_type;
typedef T &reference_type;
typedef T referenced_type;
typedef T element_type;
};
template <typename T>
struct traits<T *> {
typedef T **pointer_type;
typedef T pointed_type;
typedef T *&reference_type;
typedef T *referenced_type;
typedef T *element_type;
};
template <typename T>
struct traits<T[]> : public traits<T *> {
typedef T element_type;
};
template <typename T>
struct traits<T &> : public traits<T> {
};
template <>
struct traits<void> {
typedef void *pointer_type;
typedef void pointed_type;
typedef void reference_type;
typedef void referenced_type;
};
//****************************************************************************
// Qualifier removers
//****************************************************************************
template <typename T>
struct remove_const {
typedef T type;
};
template <typename T>
struct remove_const<const T> {
typedef T type;
};
template <typename T>
struct remove_ref {
typedef T type;
};
template <typename T>
struct remove_ref<T &> {
typedef T type;
};
template <typename T>
struct remove_cref {
typedef typename remove_const<typename remove_ref<T>::type>::type type;
};
//****************************************************************************
// TCG traits for function types
//****************************************************************************
template <typename Func>
class function_traits
{
template <typename F, bool>
struct result;
template <typename F>
struct result<F, true> {
typedef typename F::result_type type;
};
template <typename F>
struct result<F, false> {
typedef struct {
} type;
};
template <typename Q>
static typename enable_if_exists<typename Q::result_type,
char>::type
result_fun(Q *);
static double result_fun(...);
template <typename F, bool>
struct argument;
template <typename F>
struct argument<F, true> {
typedef typename F::argument_type type;
};
template <typename F>
struct argument<F, false> {
typedef void type;
};
template <typename Q>
static typename enable_if_exists<typename Q::argument_type,
char>::type
argument_fun(Q *);
static double argument_fun(...);
template <typename F, bool>
struct first_arg;
template <typename F>
struct first_arg<F, true> {
typedef typename F::first_argument_type type;
};
template <typename F>
struct first_arg<F, false> {
typedef void type;
};
template <typename Q>
static typename enable_if_exists<typename Q::first_argument_type,
char>::type
first_arg_fun(Q *);
static double first_arg_fun(...);
template <typename F, bool>
struct second_arg;
template <typename F>
struct second_arg<F, true> {
typedef typename F::second_argument_type type;
};
template <typename F>
struct second_arg<F, false> {
typedef void type;
};
template <typename Q>
static typename enable_if_exists<typename Q::second_argument_type,
char>::type
second_arg_fun(Q *);
static double second_arg_fun(...);
public:
enum { has_result = (sizeof(result_fun(typename tcg::traits<Func>::pointer_type())) == sizeof(char)),
has_argument = (sizeof(argument_fun(typename tcg::traits<Func>::pointer_type())) == sizeof(char)),
has_first_arg = (sizeof(first_arg_fun(typename tcg::traits<Func>::pointer_type())) == sizeof(char)),
has_second_arg = (sizeof(second_arg_fun(typename tcg::traits<Func>::pointer_type())) == sizeof(char)) };
typedef typename result<Func, has_result>::type ret_type;
typedef typename argument<Func, has_argument>::type arg_type;
typedef typename first_arg<Func, has_first_arg>::type arg1_type;
typedef typename second_arg<Func, has_second_arg>::type arg2_type;
};
//-----------------------------------------------------------------------
template <typename Ret>
struct function_traits<Ret()> {
enum { has_result = true,
has_argument = false,
has_first_arg = false,
has_second_arg = false };
typedef Ret ret_type;
typedef void arg_type;
typedef void arg1_type;
typedef void arg2_type;
};
template <typename Ret>
struct function_traits<Ret (*)()> : public function_traits<Ret()> {
};
template <typename Ret>
struct function_traits<Ret(&)()> : public function_traits<Ret()> {
};
//-----------------------------------------------------------------------
template <typename Ret, typename Arg>
struct function_traits<Ret(Arg)> {
enum { has_result = true,
has_argument = true,
has_first_arg = false,
has_second_arg = false };
typedef Ret ret_type;
typedef Arg arg_type;
typedef void arg1_type;
typedef void arg2_type;
};
template <typename Ret, typename Arg>
struct function_traits<Ret (*)(Arg)> : public function_traits<Ret(Arg)> {
};
template <typename Ret, typename Arg>
struct function_traits<Ret(&)(Arg)> : public function_traits<Ret(Arg)> {
};
//-----------------------------------------------------------------------
template <typename Ret, typename Arg1, typename Arg2>
struct function_traits<Ret(Arg1, Arg2)> {
enum { has_result = true,
has_first_arg = true,
has_second_arg = true };
typedef Ret ret_type;
typedef Arg1 arg1_type;
typedef Arg2 arg2_type;
};
template <typename Ret, typename Arg1, typename Arg2>
struct function_traits<Ret (*)(Arg1, Arg2)> : public function_traits<Ret(Arg1, Arg2)> {
};
template <typename Ret, typename Arg1, typename Arg2>
struct function_traits<Ret(&)(Arg1, Arg2)> : public function_traits<Ret(Arg1, Arg2)> {
};
//******************************************************************************
// TCG traits for output container readers
//******************************************************************************
template <typename Reader, typename OutputData = typename Reader::value_type>
struct container_reader_traits {
typedef Reader reader_type;
typedef OutputData value_type;
static void openContainer(reader_type &reader) { reader.openContainer(); }
static void addElement(reader_type &reader, const value_type &data) { reader.addElement(data); }
static void closeContainer(reader_type &reader) { reader.closeContainer(); }
};
//************************************************************************************
// Notable Test traits
//************************************************************************************
template <typename T>
struct is_floating_point {
enum { value = false };
};
template <>
struct is_floating_point<float> {
enum { value = true };
};
template <>
struct is_floating_point<double> {
enum { value = true };
};
template <>
struct is_floating_point<long double> {
enum { value = true };
};
//-----------------------------------------------------------------------
template <typename T>
struct is_function {
enum { value = function_traits<T>::has_result };
};
template <typename T>
struct is_functor {
template <typename Q>
static typename enable_if_exists<typename Q::result_type,
char>::type
result(Q *);
static double result(...);
enum { value = (sizeof(result(typename tcg::traits<T>::pointer_type())) == sizeof(char)) };
};
} // namespace tcg
#endif // TCG_TRAITS_H