diff --git a/Framework/StackInterface/Stack.h b/Framework/StackInterface/Stack.h index 74e13fdb801f97884c5c2ce27996d3eca610df3d..86bd98180fc68fc70d32f2d9a9714eb51cb6f87f 100644 --- a/Framework/StackInterface/Stack.h +++ b/Framework/StackInterface/Stack.h @@ -15,6 +15,7 @@ #include <corsika/stack/StackIteratorInterface.h> // must be after StackIteratorInterface #include <corsika/stack/SecondaryView.h> +#include <corsika/utl/MetaProgramming.h> #include <stdexcept> #include <type_traits> @@ -72,11 +73,7 @@ namespace corsika::stack { * if StackDataType is a reference member we *HAVE* to initialize * it in the constructor, this is typically needed for SecondaryView */ - template < - typename _StackDataType = StackDataType, - typename = std::enable_if<std::is_same<StackDataType, _StackDataType>::value && - std::is_reference<_StackDataType>::value, - void>> + template <typename _ = StackDataType, typename = utl::enable_if<std::is_reference<_>>> Stack(StackDataType vD) : fData(vD) {} @@ -89,11 +86,8 @@ namespace corsika::stack { * stacks, where the inner data container is always a reference * and cannot be initialized here. */ - template < - typename... Args, typename _StackDataType = StackDataType, - typename = std::enable_if<std::is_same<StackDataType, _StackDataType>::value && - !std::is_reference<_StackDataType>::value, - void>> + template <typename... Args, typename _ = StackDataType, + typename = utl::disable_if<std::is_reference<_>>> Stack(Args... args) : fData(args...) {} diff --git a/Framework/Utilities/CMakeLists.txt b/Framework/Utilities/CMakeLists.txt index 2f9b8e1e40676418860ba5217677e56222834685..f55df7645645fe362070a467e563983c5bcac6fc 100644 --- a/Framework/Utilities/CMakeLists.txt +++ b/Framework/Utilities/CMakeLists.txt @@ -28,6 +28,7 @@ set ( Bit.h Singleton.h CorsikaFenv.h + MetaProgramming.h ) set ( diff --git a/Framework/Utilities/MetaProgramming.h b/Framework/Utilities/MetaProgramming.h new file mode 100644 index 0000000000000000000000000000000000000000..73aa19f82a7b481d54e03e9126fe5d8327b4247c --- /dev/null +++ b/Framework/Utilities/MetaProgramming.h @@ -0,0 +1,66 @@ + +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#ifndef _include_corsika_utilties_meta_programming_h_ +#define _include_corsika_utilties_meta_programming_h_ + +#include <type_traits> + +/** + \file MetaProgramming.h + + Tools to emulate conditional compilation of method overloads. + + ``` + #include <corsika/utl/MetaProgramming.h> + + template <class T> + struct Foo { + template <class U, class = corsika::utl::enable_if<std::reference<U>>> + void enable_only_if_U_is_reference(U x) {} + + template <class _ = T, class = corsika::utl::disable_if<std::reference<_>>> + void enable_only_if_T_is_not_reference() {} + }; + ``` + + To combine traits, use boost::mp11::mp_and or boost::mp11::mp_or. + + ``` + #include <corsika/utl/MetaProgramming.h> + #include <boost/mp11.hpp> + + template <class T> + struct Foo { + template <class U, class = corsika::utl::enable_if< + boost::mp11::mp_and<std::is_reference<T>, std::is_const<T>> + > + void enable_only_if_U_is_const_reference(U x) {} + }; + ``` + + Common combined traits may be implemented in this header. For example: + ``` + template <class T> + using is_cref = boost::mp11::mp_and<std::is_reference<T>, std::is_const<T>>; + ``` +} +*/ + +namespace corsika::utl { + template <class Trait> + using enable_if = typename std::enable_if<(Trait::value == true)>::type; + + template <class Trait> + using disable_if = typename std::enable_if<(Trait::value == false)>::type; +} // namespace corsika::utl + +#endif