--- /dev/null
+New: The struct is_base_of_all is a generalization of std::is_base_of
+to template parameter packs and tests if all classes in the parameter pack
+have a given class as base class or are this class.
+<br>
+(Daniel Arndt, 2017/08/21)
DEAL_II_NAMESPACE_OPEN
+namespace
+{
+ // helper struct for is_base_of_all
+ template<bool... Types> struct BoolStorage;
+}
+
+/**
+ * This struct is a generalization of std::is_base_of<Base, Derived>
+ * to template parameter packs and tests if all of the Derived...
+ * classes have Base as base class or are Base itself. The result
+ * is stored in the member variable value.
+ */
+template<class Base, class... Derived>
+struct is_base_of_all
+{
+ static constexpr bool value =
+ std::is_same<BoolStorage<std::is_base_of<Base,Derived>::value..., true>,
+ BoolStorage<true, std::is_base_of<Base,Derived>::value...>>::value;
+};
+
+
+
template <bool, typename> struct constraint_and_return_value;
template <class... FETypes>
FECollection<dim,spacedim>::FECollection (const FETypes &... fes)
{
+ static_assert(is_base_of_all<FiniteElement<dim, spacedim>, FETypes...>::value,
+ "Not all of the input parameters are derived from FiniteElement<dim, spacedim>!");
+
+ // We want to call 'push_back' for each of the arguments. To do so parameter
+ // pack expansion comes in handy. Unfortunately, we can't just write
+ // push_back(fes)...;
+ // but have to treat this as arguments to some function which doesn't need
+ // to do anything with it. Now,
+ // [](...) {}(push_back(fes)...);
+ // doesn't work as well because the ellipsis cannot deal with no parameters
+ // at all. Hence, we extend the return value of each of the return values
+ // by zero using the comma operator.
[](...) {}((push_back(fes),0)...);
}