/usr/include/dune/pdelab/common/concept.hh is in libdune-pdelab-dev 2.4.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_PDELAB_COMMON_CONCEPT_HH
#define DUNE_PDELAB_COMMON_CONCEPT_HH
#include <type_traits>
#include <utility>
#include <tuple>
#include <dune/pdelab/common/typeutilities.hh>
#include <dune/pdelab/common/typelist.hh>
namespace Dune {
namespace PDELab {
// Forward declaration
template<class C, class... T>
constexpr bool models();
/**
* \brief Namespace for concepts
*
* This namespace contains helper functions for
* concept definitions and the concept definitions
* themselves.
*/
namespace Concept {
/**
* \brief Base class for refined concepts.
*
* If a new concept should refine one or more existing concepts,
* this can be achieved by deriving the new concept from
* Refines<C1,...,CN> where C1, ..., CN are the concepts
* to be refined. If you want to refine several concepts
* they should all be put in a single Refines<...> base
* class.
*
* \tparam BaseConcepts The list of concepts to be refined.
*/
template<class... BaseConcepts>
struct Refines
{
typedef TypeList<BaseConcepts...> BaseConceptList;
};
namespace Imp {
// #############################################################################
// # All functions following here are implementation details
// # for the models() function below.
// #############################################################################
// Here is the implementation of the concept checking.
// The first two overloads do the magic for checking
// if the requirements of a concept are satisfied.
// The rest is just for checking base concepts in case
// of refinement.
// This overload is present if type substitution for
// C::require(T...) is successful, i.e., if the T...
// matches the requirement of C. In this case this
// overload is selected because PriorityTag<1>
// is a better match for PrioriryTag<42> than
// PriorityTag<0> in the default overload.
template<class C, class... T,
decltype(std::declval<C>().require(std::declval<T>()...), 0) =0>
constexpr std::true_type matchesRequirement(PriorityTag<1>)
{ return {}; }
// If the above overload is ruled out by SFINAE because
// the T... does not match the requirements of C, then
// this default overload drops in.
template<class C, class... T>
constexpr std::false_type matchesRequirement(PriorityTag<0>)
{ return {}; }
// An empty list C of concepts is always matched by T...
template<class...T>
constexpr bool modelsConceptList(TypeList<>)
{ return true; }
// A nonempty list C0,..,CN of concepts is modeled
// by T... if it models the concept C0
// and all concepts in the list C1,..,CN.
template<class...T, class C0, class... CC>
constexpr bool modelsConceptList(TypeList<C0, CC...>)
{ return models<C0, T...>() and modelsConceptList<T...>(TypeList<CC...>()); }
// If C is an unrefined concept, then T... models C
// if it matches the requirement of C.
template<class C, class... T>
constexpr bool modelsConcept(PriorityTag<0>)
{ return matchesRequirement<C, T...>(PriorityTag<42>()); }
// If C is a refined concept, then T... models C
// if it matches the requirement of C and of
// all base concepts.
//
// This overload is used if C::BaseConceptList exists
// due to its higher priority.
template<class C, class... T,
decltype(typename C::BaseConceptList(), 0) = 0>
constexpr bool modelsConcept(PriorityTag<1>)
{ return matchesRequirement<C, T...>(PriorityTag<42>()) and modelsConceptList<T...>(typename C::BaseConceptList()); }
// #############################################################################
// # All functions following here are implementation details for the
// # for the tupleEntriesModel() function below.
// #############################################################################
template<class C, class First>
constexpr auto allModel()
-> std::integral_constant<bool, models<C, First>()>
{ return {}; }
template<class C, class First, class... Other>
constexpr auto allModel()
-> std::integral_constant<bool, models<C, First>() and allModel<C, Other...>()>
{ return {}; }
template<class C, class... T>
constexpr auto tupleEntriesModel(const std::tuple<T...>&)
-> decltype(allModel<C, T...>())
{ return {}; }
} // namespace Dune::Concept::Imp
// #############################################################################
// # The method tupleEntriesModel() does the actual check if the types in a tuple
// # model a concept using the implementation details above.
// #############################################################################
template<class C, class Tuple>
constexpr auto tupleEntriesModel()
-> decltype(Imp::tupleEntriesModel<C>(std::declval<Tuple>()))
{
return {};
}
// #############################################################################
// # The following require*() functions are just helpers that allow to
// # propagate a failed check as substitution failure. This is usefull
// # inside of a concept definition.
// #############################################################################
// Helper function for use in concept definitions.
// If the passed value b is not true, the concept will to be satisfied.
template<bool b, typename std::enable_if<b, int>::type = 0>
constexpr bool requireTrue()
{
return true;
}
// Helper function for use in concept definitions.
template<class C, class... T, typename std::enable_if<models<C, T...>(), int>::type = 0>
constexpr bool requireConcept()
{
return true;
}
// Helper function for use in concept definitions.
// This allows to avoid using decltype
template<class C, class... T, typename std::enable_if<models<C, T...>(), int>::type = 0>
constexpr bool requireConcept(T&&... t)
{
return true;
}
// Helper function for use in concept definitions.
// This checks if the concept given as first type is modelled by all types in the tuple passed as argument
template<class C, class Tuple, typename std::enable_if<tupleEntriesModel<C, Tuple>(), int>::type = 0>
constexpr bool requireConceptForTupleEntries()
{
return true;
}
// Helper function for use in concept definitions.
// If the first passed type is not convertible to the second, the concept will not be satisfied.
template<class From, class To,
typename std::enable_if< std::is_convertible<From, To>::value, int>::type = 0>
constexpr bool requireConvertible()
{
return true;
}
// Helper function for use in concept definitions.
// If passed argument is not convertible to the first passed type, the concept will not be satisfied.
template<class To, class From,
typename std::enable_if< std::is_convertible<From, To>::value, int>::type = 0>
constexpr bool requireConvertible(const From&)
{
return true;
}
// Helper function for use in concept definitions.
// This will always evaluate to true. If just allow
// to turn a type into an expression. The failure happens
// already during substitution for the type argument.
template<typename T>
constexpr bool requireType()
{
return true;
}
// Helper function for use in concept definitions.
// If first passed type is not a base class of second type, the concept will not be satisfied.
template<class Base, class Derived,
typename std::enable_if< std::is_base_of<Base, Derived>::value, int>::type = 0>
constexpr bool requireBaseOf()
{
return true;
}
// Helper function for use in concept definitions.
// If first passed type is not a base class of first arguments type, the concept will not be satisfied.
template<class Base, class Derived,
typename std::enable_if< std::is_base_of<Base, Derived>::value, int>::type = 0>
constexpr bool requireBaseOf(const Derived&)
{
return true;
}
// Helper function for use in concept definitions.
// If the passed types are not the same, the concept will not be satisfied.
template<class A, class B,
typename std::enable_if< std::is_same<A, B>::value, int>::type = 0>
constexpr bool requireSameType()
{
return true;
}
} // namespace Dune::Concept
/**
* \brief Check if concept is modeled by given types
*
* This will check if the given concept is modeled by the given
* list of types. This is true if the list of types models all
* the base concepts that are refined by the given concept
* and if it satisfies all additional requirements of the latter.
*
* Notice that a concept may be defined for a list of interacting types.
* The function will check if the given list of types matches the requirements
* on the whole list. It does not check if each individual type in the list
* satisfies the concept.
*
* This concept check mechanism is inspired by the concept checking
* facility in Eric Nieblers range-v3. For more information please
* refer to the libraries project page https://github.com/ericniebler/range-v3
* or this blog entry: http://ericniebler.com/2013/11/23/concept-checking-in-c11.
* In fact the interface provided here is almost exactly the same as in range-v3.
* However the implementation differs, because range-v3 uses its own meta-programming
* library whereas our implementation is more straight forward.
*
* \tparam C The concept to check
* \tparam T The list of type to check against the concept
*
*/
template<class C, class... T>
constexpr bool models()
{
return Concept::Imp::modelsConcept<C, T...>(PriorityTag<42>());
}
} // namespace PDELab
} // namespace Dune
#endif // DUNE_PDELAB_COMMON_CONCEPT_HH
|