Skip to content
Snippets Groups Projects
Commit fc637911 authored by Simon Praetorius's avatar Simon Praetorius
Browse files

Merge branch 'feature/referencehelper' into 'master'

Add utilities for working with `std::reference_wrapper`

See merge request core/dune-common!1100
parents da345993 da4bd702
No related branches found
No related tags found
1 merge request!1100Add utilities for working with `std::reference_wrapper`
Pipeline #43988 passed
Pipeline: Dune Nightly Test

#43990

    # Master (will become release 2.9)
    - Add helper function `resolveRef()` to transparently use `std::reference_wrapper`.
    - Add `pragma omp simd` annotations in the LoopSIMD class to improve compiler optimizations
    - deprecate Factorial in common/math.hh (use factorial function)
    ......
    ......@@ -80,6 +80,7 @@ install(FILES
    proxymemberaccess.hh
    quadmath.hh
    rangeutilities.hh
    referencehelper.hh
    reservedvector.hh
    scalarvectorview.hh
    scalarmatrixview.hh
    ......
    // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
    // vi: set et ts=4 sw=2 sts=2:
    #ifndef DUNE_COMMON_REFERENCE_HELPER_HH
    #define DUNE_COMMON_REFERENCE_HELPER_HH
    #include <type_traits>
    #include <functional>
    namespace Dune {
    namespace Impl {
    template<class T>
    class IsReferenceWrapper : public std::false_type {};
    template<class T>
    class IsReferenceWrapper<std::reference_wrapper<T>> : public std::true_type {};
    template<class T>
    class IsReferenceWrapper<const std::reference_wrapper<T>> : public std::true_type {};
    } // namespace Dune::Impl
    /**
    * \brief Helper to detect if given type is a std::reference_wrapper
    *
    * \ingroup CxxUtilities
    */
    template<class T>
    constexpr bool IsReferenceWrapper_v = Impl::IsReferenceWrapper<T>::value;
    /**
    * \brief Helper function to resolve std::reference_wrapper
    *
    * This is the overload for plain (mutable or const) l-value reference types.
    * It simply forwards the passed l-value reference.
    *
    * \ingroup CxxUtilities
    */
    template<class T>
    constexpr T& resolveRef(T& gf) noexcept
    {
    return gf;
    }
    // There's no overload for non std::reference_wrapper r-values,
    // because this may lead to undefined behavior whenever the
    // return value is stored.
    // Notice that deleting the overload is not necessary, but
    // helps to document that it is missing on purpose. It also
    // leads to nicer error messages.
    template<class T>
    const auto& resolveRef(T&& gf) = delete;
    /**
    * \brief Helper function to resolve std::reference_wrapper
    *
    * This is the overload for std::reference_wrapper<T>.
    * It resolves the reference by returning the stored
    * (mutable or const) l-value reference. It is safe
    * to call this with mutable or cost l-values
    * as well as r-values of std::reference_wrapper,
    * because the life time of the wrapped l-value reference
    * is independent of the wrapping std::reference_wrapper<T>
    * object.
    *
    * Notice that the copy created by calling this function
    * is easily elided by the compiler, since std::reference_wrapper
    * is trivially copyable.
    *
    * \ingroup CxxUtilities
    */
    template<class T>
    constexpr T& resolveRef(std::reference_wrapper<T> gf) noexcept
    {
    return gf.get();
    }
    /**
    * \brief Type trait to resolve std::reference_wrapper
    *
    * This is an alias for result of resolveRef.
    * Plain types T or const T are forwarded while
    * for T=std::reference_wrapper<S> the wrapped
    * type S is returned.
    *
    * \ingroup Utility
    */
    template<class T>
    using ResolveRef_t = std::remove_reference_t<decltype(resolveRef(std::declval<T&>()))>;
    } // namespace Dune
    #endif // DUNE_COMMON_REFERENCE_HELPER_HH
    ......@@ -298,6 +298,10 @@ dune_add_test(SOURCES rangeutilitiestest.cc
    LINK_LIBRARIES dunecommon
    LABELS quick)
    dune_add_test(SOURCES referencehelpertest.cc
    LINK_LIBRARIES dunecommon
    LABELS quick)
    dune_add_test(SOURCES reservedvectortest.cc
    LINK_LIBRARIES dunecommon
    LABELS quick)
    ......
    // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
    // vi: set et ts=4 sw=2 sts=2:
    #include <config.h>
    #include <functional>
    #include <dune/common/parallel/mpihelper.hh>
    #include <dune/common/referencehelper.hh>
    #include <dune/common/test/testsuite.hh>
    class CopyCounter
    {
    public:
    CopyCounter() : count_(0) {}
    CopyCounter(std::size_t count) : count_(count) {}
    CopyCounter(const CopyCounter& other) :
    count_(other.count_ + 1)
    {}
    auto& getCount() {
    return count_;
    }
    const auto& getCount() const {
    return count_;
    }
    void setCount(std::size_t count) {
    count_ = count;
    }
    private:
    mutable std::size_t count_;
    };
    int main (int argc, char *argv[]) try
    {
    // Set up MPI, if available
    Dune::MPIHelper::instance(argc, argv);
    Dune::TestSuite suite;
    suite.subTest([]() {
    Dune::TestSuite subSuite("Checking with mutable l-value");
    CopyCounter c;
    Dune::resolveRef(c).setCount(42);
    Dune::resolveRef(c).getCount();
    subSuite.check(Dune::resolveRef(c).getCount() == 42, "Checking resolveRef");
    subSuite.check(not Dune::IsReferenceWrapper_v<decltype(c)>, "Checking IsReferenceWrapper_v");
    return subSuite;
    }());
    suite.subTest([]() {
    Dune::TestSuite subSuite("Checking with const l-value");
    const CopyCounter c(42);
    Dune::resolveRef(c).getCount();
    subSuite.check(Dune::resolveRef(c).getCount() == 42, "Checking resolveRef");
    subSuite.check(not Dune::IsReferenceWrapper_v<decltype(c)>, "Checking IsReferenceWrapper_v");
    return subSuite;
    }());
    suite.subTest([]() {
    Dune::TestSuite subSuite("Checking with mutable reference_wrapper of mutable l-value");
    CopyCounter c;
    auto c_ref = std::ref(c);
    Dune::resolveRef(c_ref).setCount(42);
    Dune::resolveRef(c_ref).getCount();
    subSuite.check(Dune::resolveRef(c_ref).getCount() == 42, "Checking resolveRef");
    subSuite.check(Dune::IsReferenceWrapper_v<decltype(c_ref)>, "Checking IsReferenceWrapper_v");
    return subSuite;
    }());
    suite.subTest([]() {
    Dune::TestSuite subSuite("Checking with const reference_wrapper of mutable l-value");
    CopyCounter c;
    const auto c_ref = std::ref(c);
    Dune::resolveRef(c_ref).setCount(42);
    Dune::resolveRef(c_ref).getCount();
    subSuite.check(Dune::resolveRef(c_ref).getCount() == 42, "Checking resolveRef");
    subSuite.check(Dune::IsReferenceWrapper_v<decltype(c_ref)>, "Checking IsReferenceWrapper_v");
    return subSuite;
    }());
    suite.subTest([]() {
    Dune::TestSuite subSuite("Checking with mutable reference_wrapper of const l-value");
    const CopyCounter c(42);
    auto c_ref = std::ref(c);
    Dune::resolveRef(c_ref).getCount();
    subSuite.check(Dune::resolveRef(c_ref).getCount() == 42, "Checking resolveRef");
    subSuite.check(Dune::IsReferenceWrapper_v<decltype(c_ref)>, "Checking IsReferenceWrapper_v");
    return subSuite;
    }());
    suite.subTest([]() {
    Dune::TestSuite subSuite("Checking with const reference_wrapper of const l-value");
    const CopyCounter c(42);
    const auto c_ref = std::ref(c);
    Dune::resolveRef(c_ref).getCount();
    subSuite.check(Dune::resolveRef(c_ref).getCount() == 42, "Checking resolveRef");
    subSuite.check(Dune::IsReferenceWrapper_v<decltype(c_ref)>, "Checking IsReferenceWrapper_v");
    return subSuite;
    }());
    suite.subTest([]() {
    Dune::TestSuite subSuite("Checking with const reference_wrapper of const l-value (via std::cref)");
    CopyCounter c(42);
    auto c_ref = std::cref(c);
    Dune::resolveRef(c_ref).getCount();
    subSuite.check(Dune::resolveRef(c_ref).getCount() == 42, "Checking resolveRef");
    subSuite.check(Dune::IsReferenceWrapper_v<decltype(c_ref)>, "Checking IsReferenceWrapper_v");
    return subSuite;
    }());
    suite.subTest([]() {
    Dune::TestSuite subSuite("Checking with const reference_wrapper r-value of mutable l-value");
    CopyCounter c;
    Dune::resolveRef(std::ref(c)).setCount(42);
    Dune::resolveRef(std::ref(c)).getCount();
    subSuite.check(Dune::resolveRef(std::ref(c)).getCount() == 42, "Checking resolveRef");
    subSuite.check(Dune::IsReferenceWrapper_v<decltype(std::ref(c))>, "Checking IsReferenceWrapper_v");
    return subSuite;
    }());
    return suite.exit();
    }
    catch (std::exception& e) {
    std::cout << e.what() << std::endl;
    return 1;
    }
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Please register or to comment