1 #ifndef DUNE_FEM_COMMON_EXPLICITFIELDVECTOR_HH 2 #define DUNE_FEM_COMMON_EXPLICITFIELDVECTOR_HH 3 4 #include <type_traits> 5 #include <utility> 6 7 #include <dune/common/fmatrix.hh> 8 #include <dune/common/fvector.hh> 9 #include <dune/common/typeutilities.hh> 10 11 namespace Dune 12 { 13 14 namespace Fem 15 { 16 /**A variant of FieldVector which does not allow for implicit 17 * type-conversion from an to everything. 18 */ 19 template<class T, int N> 20 class ExplicitFieldVector; 21 } 22 23 template<class T, int N> 24 struct DenseMatVecTraits< Fem::ExplicitFieldVector<T, N> > 25 : DenseMatVecTraits<FieldVector<T, N> > 26 { 27 typedef Fem::ExplicitFieldVector<T, N> derived_type; 28 }; 29 30 template<class T, int N> 31 struct FieldTraits<Fem::ExplicitFieldVector<T, N> > 32 : FieldTraits<FieldVector<T, N> > 33 {}; 34 35 template<typename T, int N, int M> 36 struct IsFieldVectorSizeCorrect<Fem::ExplicitFieldVector<T, N>, M> 37 : IsFieldVectorSizeCorrect<FieldVector<T, N>, M> 38 {}; 39 40 namespace Fem { 41 42 /**std::true_type for containers containing field elements.*/ 43 template<class T> 44 struct IsFieldType 45 : std::is_same<typename FieldTraits<T>::field_type, T> 46 {}; 47 48 /**Accept implicit type conversion from any DenseVector to a field 49 * vector only if both vectors contain field elements of some type 50 * or both vectors do NOT contain field elements of some kind and 51 * the elements of the DenseVector are convertible to the field 52 * vector's elements. 53 * 54 * This inhibits the initialization of a FieldVector of complex 55 * objects like matrices from a field vector of scalars. 56 */ 57 template<class C, class T, class SFINAE = void> 58 struct AcceptElementImplicitConstruction 59 : IsFieldType<C> 60 {}; 61 62 template<class C, class T> 63 struct AcceptElementImplicitConstruction< 64 C, T, 65 std::enable_if_t<((IsFieldType<typename DenseMatVecTraits<C>::value_type>::value 66 == 67 IsFieldType<T>::value) 68 )> > 69 : std::true_type 70 {}; 71 72 template<class T, int N> 73 class ExplicitFieldVector 74 : public Dune::FieldVector<T, N> 75 { 76 typedef ExplicitFieldVector< T, N > ThisType; 77 typedef Dune::FieldVector<T, N> BaseType; 78 public: 79 //! Constructor making default-initialized vector ExplicitFieldVector()80 constexpr ExplicitFieldVector() 81 : BaseType() 82 {} 83 84 /**Redirect any general construction to the base class during 85 * explicit conversion 86 */ 87 template< class... Args, disableCopyMove< ThisType, Args... > = 0, std::enable_if_t< std::is_constructible< BaseType, Args &&... >::value, int > = 0 > ExplicitFieldVector(Args &&...args)88 explicit ExplicitFieldVector ( Args &&... args ) 89 : BaseType( std::forward< Args >( args )... ) 90 {} 91 ExplicitFieldVector(const std::initializer_list<T> & values)92 ExplicitFieldVector ( const std::initializer_list< T > &values ) 93 : BaseType( values ) 94 {} 95 96 /**Allow implicit conversion if both vectors are either 97 * composed of field-elements of some fields which can be 98 * converted into each other or if both vectors are composed of 99 * more complicated elements (which can be converted into each 100 * other), but do not allow implicit conversion of a FieldVector 101 * of scalars into a FieldVector composed of more complicated 102 * stuff. In particalar, FunctionSpace::RangeType cannot be 103 * implicitly converted to FunctionSpace::HessianRangeType. 104 */ 105 template<class C> ExplicitFieldVector(const DenseVector<C> & x,typename std::enable_if<(IsFieldVectorSizeCorrect<C,N>::value && AcceptElementImplicitConstruction<C,T>::value)>::type * dummy=0)106 ExplicitFieldVector(const DenseVector<C>& x, 107 typename std::enable_if<( 108 IsFieldVectorSizeCorrect<C, N>::value 109 && 110 AcceptElementImplicitConstruction<C, T>::value) 111 >::type* dummy=0 ) 112 : BaseType(x) 113 {} 114 115 //! Assignment operator for scalar 116 template<typename C, 117 std::enable_if_t<( 118 N == 1 && 119 AcceptElementImplicitConstruction<C, T>::value && 120 std::is_assignable<T, C>::value && 121 ! std::is_base_of<DenseVector<typename FieldTraits<T>::field_type>, T 122 >::value 123 ), int> = 0 124 > operator =(const C & c)125 ExplicitFieldVector& operator=(const C& c) 126 { 127 (*this)[0] = c; 128 return *this; 129 } 130 131 //! Inherit assignment 132 // using BaseType::operator=; <- give ambiguous overloads 133 using DenseVector<FieldVector<T, N> >::operator=; 134 135 //! copy assignment operator operator =(const ExplicitFieldVector & other)136 ExplicitFieldVector& operator=(const ExplicitFieldVector& other) 137 { 138 static_cast<BaseType&>(*this) = static_cast<const BaseType&>(other); 139 return *this; 140 } 141 142 template <typename C, std::enable_if_t<std::is_assignable<T, C>::value, int> = 0> operator =(const FieldVector<C,N> & other)143 ExplicitFieldVector& operator=(const FieldVector<C, N>& other) 144 { 145 static_cast<BaseType&>(*this) = other; 146 return *this; 147 } 148 149 template <typename C, std::enable_if_t<std::is_assignable<T, C>::value, int> = 0> operator =(const ExplicitFieldVector<C,N> & other)150 ExplicitFieldVector& operator=(const ExplicitFieldVector<C, N>& other) 151 { 152 static_cast<BaseType&>(*this) = other; 153 return *this; 154 } 155 156 }; 157 158 template<class FV> 159 struct MakeExplicit 160 { 161 using Type = FV; 162 }; 163 164 template<class Field, int Size> 165 struct MakeExplicit<FieldVector<Field, Size> > 166 { 167 using Type = ExplicitFieldVector<Field, Size>; 168 }; 169 170 template<class FV> 171 using Explicit = typename MakeExplicit<FV>::Type; 172 173 } // Fem 174 175 } // Dune 176 177 178 #endif // DUNE_FEM_COMMON_EXPLICITFIELDVECTOR_HH 179