Define tuple with variable size - c++

I want to define a boost fusion::vector in my class with the size defined by a template parameter. ATM I'm doing this with a specialization of a helper class, but I think there should be a way to do this with boost mpl/fusion or something else in just one line.
namespace detail
{
template<int dim, typename T>
struct DimensionTupleSize
{ };
template <typename T>
struct DimensionTupleSize<1>
{
enum { Dimension = 1 }
typedef boost::fusion::vector<T> type;
};
template <typename T>
struct DimensionTupleSize<2>
{
enum { Dimension = 2 }
typedef boost::fusion::vector<T, T> type;
};
template <typename T>
struct DimensionTupleSize<3>
{
enum { Dimension = 3 }
typedef boost::fusion::vector<T, T, T> type;
};
}
template<int Dim = 2>
class QuadTreeLevel
{
public:
detail::DimensionTupleSize<Dim>::type tpl;
};
Any ideas?

You can do it recursively :
template<int N, class T> struct DimensionTupleSizeImpl
{
typedef typename DimensionTupleSizeImpl<N-1,T>::type base;
typedef typename boost::fusion::result_of::push_back<base,T>::type type;
};
template<class T> struct DimensionTupleSizeImpl<0,T>
{
typedef boost::fusion::vector<> type;
};
template<int N, class T>
struct DimensionTupleSize
: boost::fusion::result_of::
as_vector<typename DimensionTupleSizeImpl<N,T>::type>
{};

If you really want a tuple rather than an array, and you're simply looking for the most succinct solution..,
#include <boost/array.hpp>
#include <boost/fusion/include/boost_array.hpp>
#include <boost/fusion/include/as_vector.hpp>
template<std::size_t DimN, typename T>
struct DimensionTupleSize : boost::fusion::result_of::as_vector<
boost::array<T, DimN>
>::type
{ };

You could use this:
template<int N, typename T>
struct create_tuple
{
private:
template<int i, int n, typename ...U>
struct creator;
template<typename ...U>
struct creator<N,N, U...>
{
typedef boost::fusion::vector<U...> type;
};
template<int i, typename ...U>
struct creator<i, N,T, U...>
{
typedef typename creator<i+1,N,T,U...>::type type;
};
public:
typedef typename creator<1,N,T>::type type;
};
template<int N, class T>
struct DimensionTupleSize
{
typedef typename create_tuple<N,T>::type type;
};

Related

Sort a tuple of integral constants at compile-time

In all the following T is std::integral_constant<int, X>.
How to design a structure and a function taking a list of integral constants as an input, and returning a std::tuple<std::integral_constant<int, X>...> in which the constants have been sorted?
template <class... T>
struct ordered_tuple;
template <class... T>
constexpr typename ordered_tuple<T...>::type make_ordered_tuple(T&&...);
The use would be:
std::integral_constant<int, 5> i5;
std::integral_constant<int, 4> i4;
std::integral_constant<int, 9> i9;
std::integral_constant<int, 1> i1;
auto tuple = make_ordered_tuple(i5, i4, i9, i1);
Here's one way to do it. I implemented merge sort, which is quite amenable to functional programming. It's less than 200 lines. Most of it is based on metafunctions I used in an earlier answer. And that is based on stuff that many other people have used in SO questions, related to basic operations on typelist's and such...
One way to improve would be to reduce the template recursion depth required, currently it is O(n). I guess that it could be O(log n) but I'm not actually sure, it depends if you can find a way to rewrite the merge metafunction. (Similarly to what Yakk pointed out in the other question.)
#include <type_traits>
template <class... T>
struct TypeList {
static constexpr const std::size_t size = sizeof...(T);
};
/***
* Concat metafunction
*/
template <typename A, typename B>
struct Concat;
template <class... As, class... Bs>
struct Concat<TypeList<As...>, TypeList<Bs...>> {
typedef TypeList<As..., Bs...> type;
};
template <typename A, typename B>
using Concat_t = typename Concat<A, B>::type;
/***
* Split metafunction
*/
template <int i, typename TL>
struct Split;
template <int k, typename... TL>
struct Split<k, TypeList<TL...>> {
private:
typedef Split<k / 2, TypeList<TL...>> FirstSplit;
typedef Split<k - k / 2, typename FirstSplit::R> SecondSplit;
public:
typedef Concat_t<typename FirstSplit::L, typename SecondSplit::L> L;
typedef typename SecondSplit::R R;
};
template <typename T, typename... TL>
struct Split<0, TypeList<T, TL...>> {
typedef TypeList<> L;
typedef TypeList<T, TL...> R;
};
template <typename T, typename... TL>
struct Split<1, TypeList<T, TL...>> {
typedef TypeList<T> L;
typedef TypeList<TL...> R;
};
template <int k>
struct Split<k, TypeList<>> {
typedef TypeList<> L;
typedef TypeList<> R;
};
// Metafunction Subdivide: Split a typelist into two roughly equal typelists
template <typename TL>
struct Subdivide : Split<TL::size / 2, TL> {};
/***
* Ordered tuple
*/
template <int X>
using int_t = std::integral_constant<int, X>;
template <class... T>
struct Ordered_List : TypeList<T...> {};
template <class... As, class... Bs>
struct Concat<Ordered_List<As...>, Ordered_List<Bs...>> {
typedef Ordered_List<As..., Bs...> type;
};
/***
* Merge metafunction
*/
template <typename A, typename B>
struct Merge;
template <typename B>
struct Merge<Ordered_List<>, B> {
typedef B type;
};
template <int a, class... As>
struct Merge<Ordered_List<int_t<a>, As...>, Ordered_List<>> {
typedef Ordered_List<int_t<a>, As...> type;
};
template <int a, class... As, int b, class... Bs>
struct Merge<Ordered_List<int_t<a>, As...>, Ordered_List<int_t<b>, Bs...>> {
typedef Ordered_List<int_t<a>, As...> A;
typedef Ordered_List<int_t<b>, Bs...> B;
typedef typename std::conditional<a <= b,
Concat_t<Ordered_List<int_t<a>>, typename Merge<Ordered_List<As...>, B>::type>,
Concat_t<Ordered_List<int_t<b>>, typename Merge<A, Ordered_List<Bs...>>::type>
>::type type;
};
template <typename A, typename B>
using Merge_t = typename Merge<A, B>::type;
/***
* Mergesort metafunction
*/
template <typename TL>
struct MergeSort;
// Boilerplate base-cases
template <>
struct MergeSort<TypeList<>> {
typedef Ordered_List<> type;
};
template <int X>
struct MergeSort<TypeList<int_t<X>>> {
typedef Ordered_List<int_t<X>> type;
};
// Inductive step
template <int X, class... Xs>
struct MergeSort<TypeList<int_t<X>, Xs...>> {
typedef TypeList<int_t<X>, Xs...> input_t;
typedef Subdivide<input_t> subdivide_t;
typedef typename MergeSort<typename subdivide_t::L>::type left_sort_t;
typedef typename MergeSort<typename subdivide_t::R>::type right_sort_t;
typedef Merge_t<left_sort_t, right_sort_t> type;
};
template <typename T>
using MergeSort_t = typename MergeSort<T>::type;
/***
* Make ordered tuple impl
*/
#include <tuple>
template <typename T>
struct MakeStdTuple;
template <class... Ts>
struct MakeStdTuple<Ordered_List<Ts...>> {
typedef std::tuple<Ts...> type;
};
template <typename T>
using MakeStdTuple_t = typename MakeStdTuple<T>::type;
template <class... T>
constexpr MakeStdTuple_t<MergeSort_t<TypeList<T...>>> make_ordered_tuple(T&&...) {
return {};
}
static_assert(std::is_same<Ordered_List<int_t<1>, int_t<2>, int_t<3>>,
MergeSort_t<TypeList<int_t<1>, int_t<2>, int_t<3>>>>::value, "Failed a unit test");
static_assert(std::is_same<Ordered_List<int_t<1>, int_t<2>, int_t<3>>,
MergeSort_t<TypeList<int_t<2>, int_t<1>, int_t<3>>>>::value, "Failed a unit test");
static_assert(std::is_same<Ordered_List<int_t<1>, int_t<2>, int_t<3>>,
MergeSort_t<TypeList<int_t<3>, int_t<2>, int_t<1>>>>::value, "Failed a unit test");
int main() {}

Is there any way of implementing the msvc_typeof in other compilers?

Looking around on the internet, I found this (MSVC typeof implementation). However, I am not sure if I could, and how I could implement this in any other compilers, not just for MSVC.
Please note: I am not looking for the register_type macro, e.t.c, as I already have implemented that myself.
Code from site:
#if defined(_MSC_VER) && _MSC_VER>=1400
namespace msvc_typeof_impl {
struct msvc_extract_type_default_param {};
template<int ID, typename T = msvc_extract_type_default_param> struct msvc_extract_type;
template<int ID> struct msvc_extract_type<ID, msvc_extract_type_default_param>
{
template<bool> struct id2type_impl;
typedef id2type_impl<true> id2type;
};
template<int ID, typename T> struct msvc_extract_type : msvc_extract_type<ID, msvc_extract_type_default_param>
{
template<> struct id2type_impl<true> //VC8.0 specific bugfeature
{
typedef T type;
};
template<bool> struct id2type_impl;
typedef id2type_impl<true> id2type;
};
template<int N> class CCounter;
// TUnused is required to force compiler to recompile CCountOf class
template<typename TUnused, int NTested = 0> struct CCountOf
{
enum
{
__if_exists(CCounter<NTested>) { count = CCountOf<TUnused, NTested + 1>::count }
__if_not_exists(CCounter<NTested>) { count = NTested }
};
};
template<class TTypeReg, class TUnused, int NValue> struct CProvideCounterValue { enum { value = NValue }; };
// type_id
#define unique_type_id(type) \
(CProvideCounterValue< \
/*register TYPE--ID*/ typename msvc_extract_type<CCountOf<type >::count, type>::id2type, \
/*increment compile-time Counter*/ CCounter<CCountOf<type >::count>, \
/*pass value of Counter*/CCountOf<type >::count \
>::value)
// Lets type_id() be > than 0
class __Increment_type_id { enum { value = unique_type_id(__Increment_type_id) }; };
// vartypeID() returns a type with sizeof(type_id)
template<int NSize> class sized { char m_pad[NSize]; };
template<typename T> typename sized<unique_type_id(T)> vartypeID(T&);
template<typename T> typename sized<unique_type_id(const T)> vartypeID(const T&);
template<typename T> typename sized<unique_type_id(volatile T)> vartypeID(volatile T&);
template<typename T> typename sized<unique_type_id(const volatile T)> vartypeID(const volatile T&);
}
#define typeof(expression) msvc_typeof_impl::msvc_extract_type<sizeof(msvc_typeof_impl::vartypeID(expression))>::id2type::type
#endif

Finding constancy of member function

How can I detect a member function has const modifier or not?
Consider the code
struct A {
int member();
int member() const;
};
typedef int (A::*PtrToMember)();
typedef int (A::*PtrToConstMember)() const;
I need something like this:
std::is_const<PtrToMember>::value // evaluating to false
std::is_const<PtrToConstMember>::value // evaluating to true
There you go:
#include <type_traits>
#include <iostream>
#include <vector>
template<typename T>
struct is_const_mem_fn {
private:
template<typename U>
struct Tester {
static_assert( // will always fail
std::is_member_function_pointer<U>::value,
"Use member function pointers only!");
// if you want to report false for types other than
// member function pointers you can just derive from
// std::false_type instead of asserting
};
template<typename R, typename U, typename...Args>
struct Tester<R (U::*)(Args...)> : std::false_type {};
template<typename R, typename U, typename...Args>
struct Tester<R (U::*)(Args...) const> : std::true_type {};
public:
static const bool value =
Tester<typename std::remove_cv<T>::type>::value;
};
struct A {
int member();
int member() const;
};
typedef int (A::*PtrToMember)();
typedef int (A::*PtrToConstMember)() const;
int main()
{
std::cout
<< is_const_mem_fn<PtrToMember>::value
<< is_const_mem_fn<const PtrToMember>::value
<< is_const_mem_fn<PtrToConstMember>::value
<< is_const_mem_fn<const volatile PtrToConstMember>::value
<< is_const_mem_fn<decltype(&std::vector<int>::size)>::value;
}
Output: 00111
EDIT: There's a corner case I forgot to account for in the original answer.
The trait above will choke on a hypothetical member function like this:
struct A {
int member(int, ...) const;
};
because there is no valid specialization of Tester that can be generated for such signature. To fix it, add the following specializations:
template<typename R, typename U, typename...Args>
struct Tester<R (U::*)(Args..., ...)> : std::false_type {};
template<typename R, typename U, typename...Args>
struct Tester<R (U::*)(Args..., ...) const> : std::true_type {};
Below is a simple type trait adapted from here that should allow this.
template <typename T>
struct is_const_mem_func : std::false_type { };
template <typename Ret, typename Class, typename... Args>
struct is_const_mem_func<Ret (Class::*)(Args...) const> : std::true_type { };

using tr2::direct_bases get nth element of result

struct T1 {};
struct T2: T1 {};
typedef tr2::direct_bases<T2>::type NEW_TYPE ;
should return my something like a touple to bases types. How can I get the nth element
of this __reflection_typelist<...>. I search for something like tuple_element for the reflection list.
You can use this simple metafunction to turn the typelist into an std::tuple:
#include <tr2/type_traits>
#include <tuple>
template<typename T>
struct dbc_as_tuple { };
template<typename... Ts>
struct dbc_as_tuple<std::tr2::__reflection_typelist<Ts...>>
{
typedef std::tuple<Ts...> type;
};
At this point, you could work with it as you would normally work with a tuple. For instance, this is how you could retrieve elements of the type list:
struct A {};
struct B {};
struct C : A, B {};
int main()
{
using namespace std;
using direct_base_classes = dbc_as_tuple<tr2::direct_bases<C>::type>::type;
using first = tuple_element<0, direct_base_classes>::type;
using second = tuple_element<1, direct_base_classes>::type;
static_assert(is_same<first, A>::value, "Error!"); // Will not fire
static_assert(is_same<second, B>::value, "Error!"); // Will not fire
}
Write your own?
template <typename R, unsigned int N> struct get;
template <typename T, typename ...Args, unsigned int N>
struct get<std::tr2::__reflection_typelist<T, Args...>, N>
{
typedef typename get<std::tr2::__reflection_typelist<Args...>, N - 1>::type type;
};
template <typename T, typename ...Args>
struct get<std::tr2::__reflection_typelist<T, Args...>, 0>
{
typedef T type;
};
Or even using first/next:
template <typename R, unsigned int N>
struct get
{
typedef typename get<typename R::next::type, N - 1>::type type;
};
template <typename R>
struct get<R, 0>
{
typedef typename R::first::type type;
};
At this point, I'd say the source code is the best documentation.

Remove reference with const references

For a parametric class C, I want to get always the "primitive" type irrespective of pointer, const or reference modifiers.
template<typename __T>
class C
{
public:
typedef std::some_magic_remove_all<__T>::type T;
}
int main()
{
C<some_type>::type a;
}
For example, for some_type equal to:
int&
int**
int*&
int const &&
int const * const
and so on
I want a is always of type int. How can I achieve it?
If you want to use the standard library more, you can do:
#include <type_traits>
template<class T, class U=
typename std::remove_cv<
typename std::remove_pointer<
typename std::remove_reference<
typename std::remove_extent<
T
>::type
>::type
>::type
>::type
> struct remove_all : remove_all<U> {};
template<class T> struct remove_all<T, T> { typedef T type; };
which removes stuff until that doesn't change the type anymore. With a more recent standard, this can be shortened to
template<class T, class U=
std::remove_cvref_t<
std::remove_pointer_t<
std::remove_extent_t<
T >>>>
struct remove_all : remove_all<U> {};
template<class T> struct remove_all<T, T> { typedef T type; };
template<class T> using remove_all_t = typename remove_all<T>::type;
template<class T> struct remove_all { typedef T type; };
template<class T> struct remove_all<T*> : remove_all<T> {};
template<class T> struct remove_all<T&> : remove_all<T> {};
template<class T> struct remove_all<T&&> : remove_all<T> {};
template<class T> struct remove_all<T const> : remove_all<T> {};
template<class T> struct remove_all<T volatile> : remove_all<T> {};
template<class T> struct remove_all<T const volatile> : remove_all<T> {};
//template<class T> struct remove_all<T[]> : remove_all<T> {};
//template<class T, int n> struct remove_all<T[n]> : remove_all<T> {};
I originally also stripped extents (arrays), but Johannes noticed that this causes ambiguities for const char[], and the question doesn't mention them. If we also want to strip arrays (see also ideas mentioned in the comments), the following doesn't complicate things too much:
#include <type_traits>
template<class U, class T = typename std::remove_cv<U>::type>
struct remove_all { typedef T type; };
template<class U, class T> struct remove_all<U,T*> : remove_all<T> {};
template<class U, class T> struct remove_all<U,T&> : remove_all<T> {};
template<class U, class T> struct remove_all<U,T&&> : remove_all<T> {};
template<class U, class T> struct remove_all<U,T[]> : remove_all<T> {};
template<class U, class T, int n> struct remove_all<U,T[n]> : remove_all<T> {};
or with a helper class but a single template parameter:
#include <type_traits>
template<class T> struct remove_all_impl { typedef T type; };
template<class T> using remove_all =
remove_all_impl<typename std::remove_cv<T>::type>;
template<class T> struct remove_all_impl<T*> : remove_all<T> {};
template<class T> struct remove_all_impl<T&> : remove_all<T> {};
template<class T> struct remove_all_impl<T&&> : remove_all<T> {};
template<class T> struct remove_all_impl<T[]> : remove_all<T> {};
template<class T, int n> struct remove_all_impl<T[n]> : remove_all<T> {};
It is normal if all the variants start looking about the same ;-)
Also you can use the remove_cvref_t function, it has been available since c++20
#include <iostream>
#include <type_traits>
int main()
{
std::cout << std::boolalpha
<< std::is_same_v<std::remove_cvref_t<int>, int> << '\n'
<< std::is_same_v<std::remove_cvref_t<int&>, int> << '\n'
<< std::is_same_v<std::remove_cvref_t<int&&>, int> << '\n'
<< std::is_same_v<std::remove_cvref_t<const int&>, int> << '\n'
<< std::is_same_v<std::remove_cvref_t<const int[2]>, int[2]> << '\n'
<< std::is_same_v<std::remove_cvref_t<const int(&)[2]>, int[2]> << '\n'
<< std::is_same_v<std::remove_cvref_t<int(int)>, int(int)> << '\n';
}