Skip to content
Snippets Groups Projects
Commit 75279b42 authored by Steffen Müthing's avatar Steffen Müthing
Browse files

Merge branch 'feature/cleanup-std-utility' into 'master'

Feature/cleanup std utility

This merge request cleans up the implementation of C++14 integer
sequences and also removes an old alias of `std::declval()` in our
`Dune::Std` namespace.

Warning: After merging this merge request, any use of `Std::declval()`
will cause compilation failures.

See merge request !82
parents a3947bae 32b9d3d2
Branches
Tags
1 merge request!82Feature/cleanup std utility
......@@ -12,11 +12,21 @@ namespace Dune
namespace Std
{
#if __cpp_lib_integer_sequence >= 201304
using std::integer_sequence;
using std::index_sequence;
using std::make_integer_sequence;
using std::make_index_sequence;
using std::index_sequence_for;
#else // __cpp_lib_integer_sequence >= 201304
// integer_sequence
// ----------------
/** \brief an implementation of std::integer_sequence to be introduced in
* C++14
/** \brief an implementation of std::integer_sequence as introduced in C++14
*
* \tparam T an integer type
* \tparam ...Ints a non-type parameter pack
......@@ -27,15 +37,6 @@ namespace Dune
static_assert( std::is_integral< T >::value, "Template parameter T is required to be an integral type" );
public:
#ifndef DOXYGEN
template< class U >
struct rebind
{
typedef integer_sequence< U, static_cast< U >( Ints )... > type;
};
#endif // #ifndef DOXYGEN
/** \brief value type */
typedef T value_type;
......@@ -45,129 +46,62 @@ namespace Dune
};
// index_sequence
// --------------
// While this is similar to std::index_sequence, there is one
// major problem with the present implementation. Our index_sequence
// is only derived from integer_sequence but not equal to one.
// As a consequence template specializations that are common
// in nontrivial use cases will fail unless we take special
// care about index_sequence. The correct implementation is
// a template alias. We should switch to the correct implementation
// (i.e. a template alias) as soon as we allow this c++11 feature
// in dune-common.
/** \brief a function similar to std::index_sequence to be introduced in
* C++14
/** \brief std::index_sequence as introduced in C++14
*
* \tparam ...Ints a non-type parameter pack
*/
template< std::size_t... Ints >
class index_sequence
: public integer_sequence< std::size_t, Ints... >
{};
using index_sequence = integer_sequence< std::size_t, Ints... >;
#ifndef DOXYGEN
// make_index_sequence_impl
// ------------------------
namespace impl {
template< std::size_t N >
class make_index_sequence_impl;
template<typename T, T i, T n, T... indices>
struct _make_integer_sequence
: public _make_integer_sequence<T,i+1,n,indices...,i>
{};
template<>
class make_index_sequence_impl< 0u >
{
public:
typedef index_sequence<> type;
};
template<>
class make_index_sequence_impl< 1u >
{
public:
typedef index_sequence< 0 > type;
};
template< std::size_t N >
class make_index_sequence_impl
{
static_assert( N >= 0, "Cannot produce an index sequence of negative length" );
template< std::size_t... I1, std::size_t... I2 >
static index_sequence< I1..., (sizeof...( I1 )+I2)... >
add ( index_sequence< I1... >, index_sequence< I2... > )
template<typename T, T n, T... indices>
struct _make_integer_sequence<T,n,n,indices...>
{
return index_sequence< I1..., (sizeof...( I1 )+I2)... >();
}
public:
typedef decltype( add( typename make_index_sequence_impl< N/2 >::type(), typename make_index_sequence_impl< N-N/2 >::type() ) ) type;
};
#endif // #ifndef DOXYGEN
using type = integer_sequence<T,indices...>;
};
}
// make_index_sequence
// -------------------
#endif // DOXYGEN
/** \fn make_index_sequence
*
* \brief a function similar to std::make_index_sequence to be introduced
* in C++14
*
* \tparam N requested size of index sequence
*/
template< std::size_t N >
static constexpr inline typename make_index_sequence_impl< N >::type make_index_sequence ()
{
return typename make_index_sequence_impl< N >::type();
}
template<typename T, T n>
using make_integer_sequence = typename impl::_make_integer_sequence<T,0,n>::type;
template<std::size_t n>
using make_index_sequence = make_integer_sequence<std::size_t,n>;
#ifndef DOXYGEN
// make_integer_sequence
// ---------------------
namespace impl {
/** \fn make_integer_sequence
*
* \brief a function similar to std::make_integer_sequence to be
* introduced in C++14
*
* \tparam T an integer type
* \tparam N requested size of integer sequence
*/
template< class T, T N >
static constexpr inline typename make_index_sequence_impl< N >::type::template rebind< T >::type
make_integer_sequence ()
{
return typename make_index_sequence_impl< N >::type::template rebind< T >::type();
}
// This is a workaround for clang bug 14858 (https://llvm.org/bugs/show_bug.cgi?id=14858)
// in a template alias declaration, clang always deduces sizeof...(T) as 1, if the template
// alias is evaluated with an unpacked template parameter pack (instead of one that is explicitly
// constructed as a list of types at the call site. This is slightly braindead (and has been around
// since at least clang 3.0).
// As a workaround, we lift the computation into a struct definition.
template<typename... T>
struct _get_pack_length
: public std::integral_constant<std::size_t,sizeof...(T)>
{};
}
#endif // DOXYGEN
// index_sequence_for
// ------------------
template<typename... T>
using index_sequence_for = make_index_sequence<impl::_get_pack_length<T...>{}>;
/** \fn index_sequence_for
*
* \brief a function similar to std::index_sequence_for to be introduced
* in C++14
*
* \tparam ...T a type parameter pack
*/
template< class... T >
static constexpr inline typename make_index_sequence_impl< sizeof...( T ) >::type
index_sequence_for ()
{
return typename make_index_sequence_impl< sizeof...( T ) >::type();
}
#endif // __cpp_lib_integer_sequence >= 201304
using std::declval;
} // namespace Std
......
......@@ -18,9 +18,9 @@ array_to_tuple_impl ( const std::array< T, sizeof...( Ints ) > &array, Dune::Std
template< class T, std::size_t N >
auto array_to_tuple ( const std::array< T, N > &array )
-> decltype( array_to_tuple_impl( array, Dune::Std::make_index_sequence< N >() ) )
-> decltype( array_to_tuple_impl( array, Dune::Std::make_index_sequence< N >{} ) )
{
return array_to_tuple_impl( array, Dune::Std::make_index_sequence< N >() );
return array_to_tuple_impl( array, Dune::Std::make_index_sequence< N >{} );
}
int main ( int, char** )
......@@ -28,7 +28,7 @@ int main ( int, char** )
using Dune::operator<<;
std::array< int, 4 > array{{ 1, 2, 3, 4 }};
auto tuple = array_to_tuple_impl( array, Dune::Std::make_index_sequence< 4 >() );
auto tuple = array_to_tuple_impl( array, Dune::Std::make_index_sequence< 4 >{} );
std::cout << Dune::className( tuple ) << std::endl;
std::cout << tuple << std::endl;
}
......@@ -87,9 +87,9 @@ namespace Dune {
template<class... Args, class Functor>
auto genericTransformTupleBackend(std::tuple<Args...>& t, Functor& f) ->
decltype(genericTransformTupleBackendImpl(t, f,Std::make_index_sequence<sizeof...(Args)>()))
decltype(genericTransformTupleBackendImpl(t, f,Std::index_sequence_for<Args...>{}))
{
return genericTransformTupleBackendImpl(t, f,Std::make_index_sequence<sizeof...(Args)>());
return genericTransformTupleBackendImpl(t, f,Std::index_sequence_for<Args...>{});
}
#endif
......@@ -193,9 +193,9 @@ namespace Dune {
template<class T>
inline auto operator()(T&& t) ->
decltype(this->apply(t,Std::make_index_sequence<sizeof...(Args)>())) const
decltype(this->apply(t,Std::index_sequence_for<Args...>{})) const
{
return apply(t,Std::make_index_sequence<sizeof...(Args)>());
return apply(t,Std::index_sequence_for<Args...>{});
}
};
......
......@@ -292,7 +292,7 @@ namespace Dune
{};
template<typename T, typename I>
struct _is_indexable<T,I,typename std::enable_if<(sizeof(Std::declval<T>()[Std::declval<I>()]) > 0),int>::type>
struct _is_indexable<T,I,typename std::enable_if<(sizeof(std::declval<T>()[std::declval<I>()]) > 0),int>::type>
: public std::true_type
{};
......@@ -348,7 +348,7 @@ namespace Dune
// version for types supporting the subscript operation
template<typename T>
struct _is_indexable<T,decltype(Std::declval<T>()[0],0)>
struct _is_indexable<T,decltype(std::declval<T>()[0],0)>
: public std::true_type
{};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment