代码之家  ›  专栏  ›  技术社区  ›  Michael Lydeamore

将boost odeint与std::map和自定义向量空间代数一起使用时,没有可行的重载“=”

  •  2
  • Michael Lydeamore  · 技术社区  · 7 年前

    the boost documentation

    编译时,出现以下错误:

    In file included from /usr/local/include/boost/numeric/odeint.hpp:32:
    In file included from /usr/local/include/boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp:25:
    In file included from /usr/local/include/boost/numeric/odeint/stepper/base/explicit_error_stepper_fsal_base.hpp:31:
    /usr/local/include/boost/numeric/odeint/util/copy.hpp:43:12: error: no viable overloaded '='
            to = from;
    
    ...
    
    note: candidate function not viable: 'this' argument has type 'const DeterministicStateType', but method is not marked const
    DeterministicStateType& operator=(const DeterministicStateType& a)
    

    我不是C++专家,但这似乎意味着=方法需要是常量,这对我来说没有意义。

    MWE:

    #include <iostream>
    #include <map>
    #include <boost/numeric/odeint.hpp>
    #include <boost/operators.hpp>
    
    namespace pl = std::placeholders;
    
    class DeterministicStateType :
        boost::additive1< DeterministicStateType ,
        boost::additive2< DeterministicStateType , double ,
        boost::multiplicative2< DeterministicStateType , double > > >
    {
    public:
        DeterministicStateType(std::map<std::string, double> map) : mMap(map)
        {}
    
        DeterministicStateType() {}
    
        DeterministicStateType(const DeterministicStateType &p)
        {
            DeterministicStateType(p.mMap);
        }
    
        std::map<std::string, double> mMap;
    
        DeterministicStateType& operator+=(const DeterministicStateType &p)
        {
            for (std::map<std::string, double>::const_iterator it = p.mMap.begin(); it != p.mMap.end(); it++)
            {
                mMap[it->first] = mMap[it->first] + it->second;
            }
    
            return *this;
        }
    
        DeterministicStateType& operator+=(double a)
        {
            for (std::map<std::string, double>::const_iterator it = mMap.begin(); it != mMap.end(); it++)
            {
                mMap[it->first] += a;
            }
    
            return *this;
        }
    
        DeterministicStateType& operator*=(const double a)
        {
            for (std::map<std::string, double>::const_iterator it = mMap.begin(); it != mMap.end(); it++)
            {
                mMap[it->first] *= it->second;
            }
    
            return *this;
        }
    
        DeterministicStateType& operator=(const DeterministicStateType& a)
        {
            mMap.clear();
            std::map<std::string, double> map2 = a.mMap;
            for (std::map<std::string, double>::iterator it = map2.begin() ; it != map2.end(); it++)
            {
                mMap[it->first] = it->second;
            }
    
            return *this;
        }        
    };
    
    DeterministicStateType operator/( const DeterministicStateType &p1 , const DeterministicStateType &p2 )
    {
        std::map<std::string, double> map;
        std::map<std::string, double> p2map = p2.mMap;
        for (std::map<std::string, double>::const_iterator it = p1.mMap.begin() ; it != p1.mMap.end() ; it++)
        {
            map[it->first] = it->second / p2map[it->first];
        }
        return DeterministicStateType(map);
    }
    
    DeterministicStateType abs( const DeterministicStateType &p )
    {
        std::map<std::string, double> map;
        for (std::map<std::string, double>::const_iterator it = p.mMap.begin() ; it != p.mMap.end() ; it++)
        {
            map[it->first] = std::abs(it->second);
        }
        return DeterministicStateType(map);
    }
    
    namespace boost { namespace numeric { namespace odeint {
        template<>
        struct vector_space_norm_inf< DeterministicStateType >
        {
            typedef double result_type;
            double operator()( const DeterministicStateType &p ) const
            {
                using std::abs;
                double max = 0;
                for (std::map<std::string, double>::const_iterator it = p.mMap.begin(); it != p.mMap.end(); it++)
                {
                    if (abs(it->second) > max)
                    {
                        max = abs(it->second);
                    }
                }
                return max;
            }
        };
    }}}
    
    namespace boost { namespace numeric { namespace odeint {
    
        template< >
        struct is_resizeable<DeterministicStateType>
        {
            typedef boost::true_type type;
            const static bool value = type::value;
        };
    
        template< >
        struct same_size_impl<DeterministicStateType, DeterministicStateType>
        {
            static bool same_size(const DeterministicStateType &v1, const DeterministicStateType &v2)
            {
                return v1.mMap.size() == v2.mMap.size();
            }
        };
    
        template< >
        struct resize_impl<DeterministicStateType, DeterministicStateType>
        {
            static void resize(DeterministicStateType &v1, const DeterministicStateType &v2)
            {
                for (std::map<std::string, double>::const_iterator it = v2.mMap.begin() ; it != v2.mMap.end() ; it++)
                {
                    if (v1.mMap.count(it->first) == 0)
                    {
                        v1.mMap[it->first] = 0;
                    }
                }
            }
        };
    }}}
    
    void derivative(const DeterministicStateType p, DeterministicStateType &dpdt, const double t) {}
    
    using namespace boost::numeric::odeint;
    int main(int argc, char *argv[])
    {
        std::map<std::string, double> x0; x0["A"]=1.0; x0["B"]=1.0;
        typedef runge_kutta_dopri5<DeterministicStateType, double, DeterministicStateType, double, vector_space_algebra> stepper_type;
        integrate_adaptive( make_dense_output(1e-6, 1e-6, stepper_type()) ,
            derivative, DeterministicStateType(x0), 0.0, 300.0, 0.00001);
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   sehe    7 年前

    复制赋值运算符将rhs作为非常量

    DeterministicStateType &operator=(DeterministicStateType &a) {
    

    当调用代码中的源代码为const时,这既不是必需的,也不会编译。只需通过添加常量来修复它:

    DeterministicStateType &operator=(DeterministicStateType const& a) {
    

    State &operator=(State const&a) {
        mMap = a.mMap;
        return *this;
    }
    

    State &operator=(State const&a) = default;
    

    等等,为什么我的错误信息还在这里?

    integrate_adaptive . 临时约束仅限于 const& ,从不 & DeterministicStateType 在调用之前,通过引用传递它,而不是临时 DeterministicStateType(x0) :

    int main() {
        DeterministicStateType x0 { { {"A", 1.0}, {"B", 1.0} } };
        typedef runge_kutta_dopri5<DeterministicStateType, double, DeterministicStateType, double, vector_space_algebra>
            stepper_type;
        integrate_adaptive(make_dense_output(1e-6, 1e-6, stepper_type()), derivative, x0, 0.0,
                           300.0, 0.00001);
    }
    

    简化代码

    在这个简化版本中,我使用了一个名称空间 mMap

    Live On Wandbox

    #include <boost/numeric/odeint.hpp>
    #include <boost/operators.hpp>
    #include <iostream>
    #include <map>
    
    namespace Deterministic {
    
        class State : boost::additive1<State,
                          boost::additive2<State, double, 
                              boost::multiplicative2<State, double> > >
        {
          public:
            using Map = std::map<std::string, double>;
            State(Map const& map) : mMap(map) {}
            State() = default;
            State(const State &p) = default;
            State &operator=(State const&a) = default;
    
            State &operator+=(const State &p) {
                for (auto& p : p.mMap) mMap[p.first] += p.second;
                return *this;
            }
    
            State &operator+=(double a) {
                for (auto& p : mMap)
                    p.second += a;
                return *this;
            }
    
            State &operator*=(double f) {
                for (auto& p : mMap) mMap[p.first] *= f;
                return *this;
            }
    
            friend State abs(const State &p) {
                using std::abs;
                auto map = p.mMap;
    
                for(auto& e : map)
                    e.second = abs(e.second);
    
                return map;
            }
    
            friend State operator/(const State &p1, const State &p2) {
                auto map = p1.mMap;
    
                for(auto& e : map)
                    e.second /= p2.mMap.at(e.first);
    
                return map;
            }
    
            friend double vector_space_norm_inf_impl(State const& p) {
                double max = 0;
                using std::abs;
                for (auto& el : p.mMap)
                    max = std::max(abs(el.second), max);
                return max;
            }
    
            size_t size() const { return mMap.size(); }
    
            void resize(State const& other) {
                for (auto& el : other.mMap)
                    mMap[el.first] += 0; // inserts if non-existent
            }
    
          private:
            Map mMap;
        };
    }
    
    using DeterministicStateType = Deterministic::State;
    
    namespace boost { namespace numeric { namespace odeint {
        template <> struct vector_space_norm_inf<DeterministicStateType> {
            typedef double result_type;
            double operator()(const DeterministicStateType &p) const { return vector_space_norm_inf_impl(p); }
        };
    
        template <> struct is_resizeable<DeterministicStateType> {
            typedef boost::true_type type;
            const static bool value = type::value;
        };
    
        template <> struct same_size_impl<DeterministicStateType, DeterministicStateType> {
            static bool same_size(const DeterministicStateType &v1, const DeterministicStateType &v2) {
                return v1.size() == v2.size();
            }
        };
    
        template <> struct resize_impl<DeterministicStateType, DeterministicStateType> {
            static void resize(DeterministicStateType &v1, const DeterministicStateType &v2) {
                v1.resize(v2);
            }
        };
    } } }
    
    void derivative(const DeterministicStateType, DeterministicStateType &, const double) {}
    
    using namespace boost::numeric::odeint;
    
    int main() {
        DeterministicStateType x0 { { {"A", 1.0}, {"B", 1.0} } };
        typedef runge_kutta_dopri5<DeterministicStateType, double, DeterministicStateType, double, vector_space_algebra>
            stepper_type;
        integrate_adaptive(make_dense_output(1e-6, 1e-6, stepper_type()), derivative, x0, 0.0,
                           300.0, 0.00001);
    }
    

    除了坏掉的编译器