Skip to content
Snippets Groups Projects
Commit 74dcb0ce authored by Carsten Gräser's avatar Carsten Gräser
Browse files

Add hybridSize() to statically/dynamically query the size of a "container"

parent 12b54196
Branches
No related tags found
No related merge requests found
Checking pipeline status
......@@ -9,6 +9,7 @@ namespace Dune {
namespace Solvers {
// Everything in the next namespace block is just used to implement integralRangeFor
namespace Imp {
template<class ST, ST begin, ST end>
......@@ -110,6 +111,123 @@ void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args)
}
// Everything in the next namespace block is just used to implement StaticSize, HasStaticSize, hybridSize
namespace Imp {
// As a last resort try if there's a static constexpr size()
template<class T>
constexpr auto staticSize(const T*, const PriorityTag<0>&)
-> decltype(std::integral_constant<std::size_t,T::size()>())
{
return {};
}
// Try if class has constexpr default constructor and size method
template<class T>
constexpr auto staticSize(const T*, const PriorityTag<1>&)
-> decltype(std::integral_constant<std::size_t,T().size()>())
{
return {};
}
// Try if tuple_size is implemented for class
template<class T>
constexpr auto staticSize(const T*, const PriorityTag<2>&)
-> decltype(std::integral_constant<std::size_t,std::tuple_size<T>::value>())
{
return {};
}
template<class T>
constexpr std::false_type hasStaticSize(const T* t, const PriorityTag<0>& p)
{
return {};
}
template<class T>
constexpr auto hasStaticSize(const T* t, const PriorityTag<1>& p)
-> decltype(staticSize(t ,PriorityTag<42>()), std::true_type())
{
return {};
}
}
/**
* \brief Check if type is a statically sized container
*
* \ingroup Utility
*
* Derives from std::true_type or std::false_type
*/
template<class T>
struct HasStaticSize :
public decltype(Imp::hasStaticSize((typename std::decay<T>::type*)(nullptr), PriorityTag<42>()))
{};
/**
* \brief Obtain size of statically sized container
*
* \ingroup Utility
*
* Derives from std::integral_constant<std::size_t, size>
*/
template<class T>
struct StaticSize :
public decltype(Imp::staticSize((typename std::decay<T>::type*)(nullptr), PriorityTag<42>()))
{};
/**
* \brief Hybrid size query
*
* \tparam T Type of container whose size is queried
*
* \param t Container whose size is queried
*
* This function is hybrid in the sense that it returns a statically
* encoded size, i.e., an integral_constant if possible and the
* dynamic result of the t.size() method otherwise.
*
* This is the static-size overload which returns the size i
* as std::integral_constant<std::size_t, i>.
*/
template<class T,
std::enable_if_t<HasStaticSize<T>::value, int> = 0>
auto hybridSize(const T& t)
{
return Imp::staticSize((T*)(nullptr), PriorityTag<42>());
}
/**
* \brief Hybrid size query
*
* \tparam T Type of container whose size is queried
*
* \param t Container whose size is queried
*
* This function is hybrid in the sense that it returns a statically
* encoded size, i.e., an integral_constant if possible and the
* dynamic result of the *.size() method otherwise.
*
* This is the dynamic-size overload which returns the result
* of t.size().
*/
template<class T,
std::enable_if_t<not HasStaticSize<T>::value, int> = 0>
auto hybridSize(const T& t)
{
return t.size();
}
} // namespace Solvers
} // namespace Dune
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment