Skip to content
This repository has been archived by the owner on Jun 18, 2021. It is now read-only.

Commit

Permalink
Merge pull request #3 from steinwurf/fix-const-baget-issues
Browse files Browse the repository at this point in the history
Fix const baget issues
  • Loading branch information
jepkri committed Jun 23, 2016
2 parents 72d7f12 + fd1fff4 commit 87d28c2
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 33 deletions.
3 changes: 2 additions & 1 deletion NEWS.rst
Expand Up @@ -6,7 +6,8 @@ every change, see the Git log.

Latest
------
* tbd
* Minor: Now ignoring ``const`` and ``volatile`` qualifiers on types.
* Patch: Fixed bug in const version of ``type_storage::baget()``

2.1.0
-----
Expand Down
103 changes: 74 additions & 29 deletions src/type-storage/type_storage.hpp
Expand Up @@ -29,9 +29,8 @@ namespace type_storage
/// remaining parameter pack Ts... when a type match has been found.
template<template<class, class> class P,
int i, typename U, typename... Ts>
struct find_type<P, i, U, true, Ts...>
: find_type<P, i+1, U, false, Ts...>

struct find_type<P, i, U, true, Ts...> :
find_type<P, i+1, U, false, Ts...>
{
/// specifies the index of the found type
template<typename... Types>
Expand All @@ -48,8 +47,8 @@ namespace type_storage
/// recursion (recurses until U == T )
template<template<class, class> class P,
int i, typename U, typename T, typename... Ts>
struct find_type<P, i, U, false, T, Ts...>
: find_type<P, i, U, P<U, T>::value, Ts...>
struct find_type<P, i, U, false, T, Ts...> :
find_type<P, i, U, P<U, T>::value, Ts...>
{ };

/// Finds index of type U in template parameter pack Ts using find_type
Expand All @@ -61,62 +60,108 @@ namespace type_storage
static const size_t value =
find_type<P, 0, U, false, Ts...>::template index <Ts...>::value;
};

/// Below helper structs are implementations of c++14 functionality with
/// same name, can be discarded for c++14.

/// Remove constness from type T
template<class T>
struct remove_const
{
using type = T;
};

/// Remove constness from type T, specialized for const types
template<class T>
struct remove_const<const T>
{
using type = T;
};

/// Remove volatile from type T
template<class T>
struct remove_volatile
{
using type = T;
};

/// Remove volatile from type T, specialized for volatile types
template<class T>
struct remove_volatile<volatile T>
{
using type = T;
};

/// Remove constness and volatile from types
template<class T>
struct remove_cv
{
using type = typename remove_volatile<
typename remove_const<T>::type>::type;
};
}

// is_base_of TMP comparison struct ignoring constness of types
template<class T, class U>
struct is_same : std::is_same<typename detail::remove_cv<T>::type,
typename detail::remove_cv<U>::type>
{ };

/// Get a object of specific type T from tuple regardless of its position.
/// This function is basically a simple implementation of
/// This function is basically a simple implementation of
/// C++14 std::get<T>(std::tuple<Types>&) function, using C++11 code.
/// NB: If tuple contains more than one object of the reqeusted type T,
/// the code cannot compile. Multiple objects of type different from T may
/// exist in the tuple.
/// If type T is not contained in tuple the code cannot compile.
/// @param tup the tuple of objects to look in
template<typename T, typename... Types>
auto get(std::tuple<Types...>& tup)
-> decltype(std::get<detail::find_index<std::is_same,
T, Types...>::value>(tup))
auto get(std::tuple<Types...>& tup) ->
decltype(std::get<detail::find_index<is_same, T, Types...>::value>(tup))
{
return std::get<detail::find_index<std::is_same,
T, Types...>::value>(tup);
return std::get<detail::find_index<is_same, T, Types...>::value>(tup);
}

// Const version of above
template<typename T, typename... Types>
auto get(const std::tuple<Types...>& tup)
-> decltype(std::get<detail::find_index<std::is_same,
T, Types...>::value>(tup))
auto get(const std::tuple<Types...>& tup) ->
decltype(std::get<detail::find_index<is_same, T, Types...>::value>(tup))
{
return std::get<detail::find_index<std::is_same,
T, Types...>::value>(tup);
return std::get<detail::find_index<is_same, T, Types...>::value>(tup);
}

// is_base_of TMP comparison struct ignoring constness of types
template<class T, class U>
struct is_base_of : std::is_base_of<typename detail::remove_cv<T>::type,
typename detail::remove_cv<U>::type>
{ };

/// Get an object from base type B from tuple regardless of its position.
/// This function is virtually identical to get(), however the matching
/// condition is on base types, not exact types.
/// NB: If tuple contains more than one object of a matching base type,
/// the code will not compile (static assertion). The same is valid if the
/// tuple does not contain any types with matching base.
/// Only the base type requested may cause a compile error, all other
/// types may be identical or share the same base, as long as they are
/// Only the base type requested may cause a compile error, all other
/// types may be identical or share the same base, as long as they are
/// different from type B.
/// @param tup the tuple of objects to look in
template<typename B, typename... Types>
auto baget(std::tuple<Types...>& tup)
-> decltype(std::get<detail::find_index<std::is_base_of,
B, Types...>::value>(tup))
auto baget(std::tuple<Types...>& tup) ->
decltype(std::get<detail::find_index<
is_base_of, B, Types...>::value>(tup))
{
return std::get<detail::find_index<std::is_base_of,
B, Types...>::value>(tup);
return std::get<detail::find_index<
is_base_of, B, Types...>::value>(tup);
}

// Const version of above
template<typename B, typename... Types>
auto baget(const std::tuple<Types...>& tup)
-> decltype(std::get<detail::find_index<std::is_base_of,
B, Types...>::value>(tup))
auto baget(const std::tuple<Types...>& tup) ->
decltype(std::get<detail::find_index<
is_base_of, B, Types...>::value>(tup))
{
return std::get<detail::find_index<std::is_base_of,
Types...>::value>(tup);
return std::get<detail::find_index<
is_base_of, B, Types...>::value>(tup);
}
}

4 changes: 2 additions & 2 deletions src/type-storage/wrapped_type_storage.hpp
Expand Up @@ -30,7 +30,7 @@ namespace type_storage
Wrapper<T>& get()
{
return std::get <
detail::find_index<std::is_same,
detail::find_index<is_same,
T, MessageTypes...>::value > (m_tuple);
}

Expand All @@ -39,7 +39,7 @@ namespace type_storage
const Wrapper<T>& get() const
{
return std::get <
detail::find_index<std::is_same,
detail::find_index<is_same,
T, MessageTypes...>::value > (m_tuple);
}

Expand Down
22 changes: 21 additions & 1 deletion test/src/test_type_storage.cpp
Expand Up @@ -111,4 +111,24 @@ TEST(TestTypeStorage, baget_basetype)
// auto& ba = type_storage::baget<base>(tup); // will not compile

EXPECT_EQ(a.m_c, b.m_c);
}
}

TEST(TestTypeStorage, get_baget_const)
{
const std::tuple<std::stringstream,
std::string, std::vector<char>, std::mutex, uint64_t,
special_a> tup;

const auto& ba = type_storage::baget<base>(tup);
(void) ba;

const auto& sa = type_storage::get<special_a>(tup);
(void) sa;

// Ignores const statement when searching
const auto& bac = type_storage::baget<const base>(tup);
(void) bac;

const auto& sac = type_storage::get<const special_a>(tup);
(void) sac;
}

0 comments on commit 87d28c2

Please sign in to comment.