实现与stl算法一起使用的绑定reference_wrapper

时间:2018-01-26 10:52:28

标签: c++ algorithm iterator

正如this previous question中所述,我试图能够为向量分配引用,以便在其上使用stl算法并将更改反映到原始数据中。

#include <vector>
#include <iostream>
#include <algorithm>

using Matrix = std::vector<std::vector<int>>;

/**
 * Class implementing std::reference_wrapper that
 * cannot be rebound after creation.
 *
 **/
template <class T>
class single_bind_reference_wrapper {

    // pointer to the original element
    T *p_;

public: // typedefs

    using type = T;

    // construct/copy/destroy
    single_bind_reference_wrapper(T& ref) noexcept : p_(std::addressof(ref)) {}
    single_bind_reference_wrapper(T&&) = delete;

    // Enable implicit convertsion from ref<T> to ref<const T>,
    // or ref<Derived> to ref<Base>
    template <class U, std::enable_if_t<std::is_convertible<U*, T*>{}, int> = 0>
    single_bind_reference_wrapper(const single_bind_reference_wrapper<U>& other) noexcept :
        p_(&other.get()) { }

    // assignment
    template <class U>
    decltype(auto) operator=(U &&u) const 
          noexcept(noexcept(std::declval<T>() = std::forward<U>(u))) {
        return get() = std::forward<U>(u);
    }

    // access
    operator T& () const noexcept { return *p_; }
    T& get() const noexcept { return *p_; }
};

void rotate_mat (Matrix &mat, int r){
    auto m = mat.size(); // Number of rows
    auto n = mat[0].size(); // Number of columns
    auto n_rings = std::min(m,n)/2; // Number of rings
    for(auto ring_i=0; ring_i<n_rings; ++ring_i){
        // The elements of the ring are stored sequentially 
        // in v_ring so it can be rotated with std::rotate 
        std::vector<single_bind_reference_wrapper<int>>  v_ring;
        std::vector<int*> v_ring_ptr;
        // Top side of the ring
        for(auto j=ring_i; j<=(n-1)-ring_i; ++j) {
            v_ring.push_back(mat[ring_i][j]);
        }
        // Right side of the ring
        for(auto i=ring_i+1; i<=(m-1)-ring_i; ++i) {
            v_ring.push_back(mat[i][(n-1)-ring_i]);
        }
        // Bottom size of the ring
        for(auto j=(n-1)-ring_i-1; j>ring_i; --j) {
            v_ring.push_back(mat[(m-1)-ring_i][j]);
        }
        // Left size of the ring
        for(auto i=(m-1)-ring_i; i>ring_i; --i) {
            v_ring.push_back(mat[i][ring_i]);
        }

        v_ring[0] = 10; // compilation error!
        // This would be my goal:
        //std::rotate(v_ring.begin(),v_ring.begin()+r%v_ring.size(),v_ring.end());
    }
};

Matrix read_matrix(int m, int n) {
    Matrix mat;
    mat.reserve(m);
    for(auto i=0; i<m; ++i) {
        mat.push_back(std::vector<int>{});
        mat[i].reserve(n);
        for(auto j=0; j<n; ++j) {
            int x; std::cin >> x;
            mat[i].push_back(x);
        }
    }
    return mat;
};

void print_matrix(Matrix &mat){
    for (auto& i : mat){
        for (auto& j : i) {
            std::cout << j << " ";
        }
        std::cout << "\n";
    }
};

int main() {
    int m,n; std::cin >> m >> n;
    int r; std::cin >> r;

    auto mat = read_matrix(m,n);
    rotate_mat(mat,r);
    print_matrix(mat);

    return 0;
}

目标是能够对std::rotate v_ring进行mat,并查看其对=原始元素的影响。从来没有,我仍然无法正确实施solution.cc: In function ‘void rotate_mat(Matrix&, int)’: solution.cc:72:21: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: v_ring[0] = 10; ^~ solution.cc:34:20: note: candidate 1: decltype(auto) single_bind_reference_wrapper<T>::operator=(U&&) const [with U = int; T = int] decltype(auto) operator=(U &&u) const ^~~~~~~~ solution.cc:13:7: note: candidate 2: constexpr single_bind_reference_wrapper<int>& single_bind_reference_wrapper<int>::operator=(single_bind_reference_wrapper<int>&&) class single_bind_reference_wrapper { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ solution.cc:72:21: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: v_ring[0] = 10; ^~ solution.cc:34:20: note: candidate 1: decltype(auto) single_bind_reference_wrapper<T>::operator=(U&&) const [with U = int; T = int] decltype(auto) operator=(U &&u) const ^~~~~~~~ solution.cc:13:7: note: candidate 2: constexpr single_bind_reference_wrapper<int>& single_bind_reference_wrapper<int>::operator=(const single_bind_reference_wrapper<int>&) class single_bind_reference_wrapper { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ solution.cc: In instantiation of ‘decltype(auto) single_bind_reference_wrapper<T>::operator=(U&&) const [with U = int; T = int]’: solution.cc:72:21: required from here solution.cc:35:47: error: using xvalue (rvalue reference) as lvalue noexcept(noexcept(std::declval<T>() = std::forward<U>(u))) { ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~ solution.cc: In instantiation of ‘decltype(auto) single_bind_reference_wrapper<T>::operator=(U&&) const [with U = int; T = int]’: solution.cc:72:21: required from here solution.cc:35:47: error: using xvalue (rvalue reference) as lvalue 运营商。

我得到的编译错误是:

        public void Log(Exception ex)
           {
         // Create an instance of StringBuilder. This class is in System.Text namespace
                StringBuilder sbExceptionMessage = new StringBuilder();
                sbExceptionMessage.Append("Exception Type" + Environment.NewLine);
                // Get the exception type
                sbExceptionMessage.Append(exception.GetType().Name);
                // Environment.NewLine writes new line character - \n
                sbExceptionMessage.Append(Environment.NewLine + Environment.NewLine);
                sbExceptionMessage.Append("Message" + Environment.NewLine);
                // Get the exception message
                sbExceptionMessage.Append(exception.Message + Environment.NewLine + Environment.NewLine);
                sbExceptionMessage.Append("Stack Trace" + Environment.NewLine);
                // Get the exception stack trace
                sbExceptionMessage.Append(exception.StackTrace + Environment.NewLine + Environment.NewLine);

                // Retrieve inner exception if any
                Exception innerException = exception.InnerException;
                // If inner exception exists
                while (innerException != null)
                {
                    sbExceptionMessage.Append("Exception Type" + Environment.NewLine);
                    sbExceptionMessage.Append(innerException.GetType().Name);
                    sbExceptionMessage.Append(Environment.NewLine + Environment.NewLine);
                    sbExceptionMessage.Append("Message" + Environment.NewLine);
                    sbExceptionMessage.Append(innerException.Message + Environment.NewLine + Environment.NewLine);
                    sbExceptionMessage.Append("Stack Trace" + Environment.NewLine);
                    sbExceptionMessage.Append(innerException.StackTrace + Environment.NewLine + Environment.NewLine);

                    // Retrieve inner exception if any
                    innerException = innerException.InnerException;
    }
}

0 个答案:

没有答案