简体   繁体   English

数学向量类通过组合

[英]mathematical vector class through composition

I started to write a class which would act much like the std::vector but with some mathematical operations. 我开始写一个类,它的行为很像std::vector但是有一些数学运算。 Mainly things like the norm of the vector and overloading important mathematical operators (+,- etc.) which will add, subtract things element wise. 主要是矢量范数和重载重要数学运算符(+,-等)之类的东西,它们将按元素进行加,减。

The class is posted below, I have used boost::operators to write all the mathematical operators and they all work flawlessly. 该类发布在下面,我使用boost::operators编写所有数学运算符,并且它们都可以完美地工作。 I have run into some problems when implementing the iterator. 在实现迭代器时,我遇到了一些问题。 I have tried to write the iterator as a nested class and use boost::iterator to get most/all of the functionality of the std::vector iterator. 我试图将迭代器编写为嵌套类,并使用boost::iterator来获取std::vector迭代器的大部分/全部功能。

This is where I have ran into trouble, the code will not compile with approximately 2 miles worth of template related error output. 这是我遇到麻烦的地方,代码将无法使用大约2英里的模板相关错误输出进行编译。 Which I can post if you are interested but is typical verbose boost template errors. 如果您有兴趣,但可以发布,但它是典型的冗长的Boost模板错误。

My question is two-fold. 我的问题有两个方面。

First is composition the best design choice? 首先,构图是最佳的设计选择吗? Might I do better with private inheritence or a decorator pattern? 使用私有继承或装饰器模式可能会做得更好吗? Or maybe someone knows of an implementation of this idea in a library? 或者,也许有人知道在图书馆中实现这种想法的方法?

Second, what am I doing wrong with the iterator? 其次,迭代器在做什么? I feel as if I am missing something fundamental in my boost::iterator implementation and would like to fix it as opposed to change my design. 我觉得好像在我的boost::iterator实现中缺少一些基本知识,并且想修复它而不是更改我的设计。

I have not included the implementation in most of the methods as they are either trivial or unimportant. 由于大多数方法微不足道或不重要,因此我并未将其包含在内。

//publicly inherits important boost::operators classes
template <class T>
class Coords: boost::arithmetic<Coords<T>
            ,boost::arithmetic<Coords<T>, T
//              ,boost::indexable<Coords<T>,int,T&
//              ,boost::dereferenceable<Coords<T>, T*>
//            >
    >
>
{
private:
    //private member
    std::vector<T> x_;
public:

    //public constructors
    Coords(int n, T x): x_(n,x){};
    Coords(int n): x_(n){};
    Coords(std::vector<T> &x);
    Coords(const Coords &rhs);

    //iterator nested class, public inherits boost::iterator_facade
    class iterator: public boost::iterator_facade<iterator, Coords<T>, std::random_access_iterator_tag>{
        private:
            typename std::vector<T>::iterator iter_;

            friend class boost::iterator_core_access;

            void increment() { iter_ = iter_++;};

            void decrement() { iter_ = iter_--;};

            void advance(int n){ iter_ = iter_+=n;};

            void equal(iterator const &other) const{
                return this->iter_ == other.iter_;
            }

            T& dereference() const {return *iter_;};

            int distance_to(iterator const &other) const{
                return this->iter_ - other.iter_;
            }

        public:
            iterator():iter_(0){};

            explicit iterator(const typename Coords<T>::iterator& it):iter_(it.iter_){};

            explicit iterator(const typename std::vector<T>::iterator& it):iter_(it){};

    };

    //methods from std::vector I would like to 'copy'
    typename Coords<T>::iterator begin(){return iterator(x_.begin());};
    typename Coords<T>::iterator end(){return iterator(x_.end());};
    typename Coords<T>::iterator operator[](std::size_t n);
    std::size_t size(){return x.size()};

    //mathematical methods
    T norm() const;
    T square() const;
    T sum() const;
    T dotProd(const Coords &rhs);

    //important operator overloads
    Coords operator+=(const T &rhs);
    Coords operator-=(const T &rhs);
    Coords operator*=(const T &rhs);
    Coords operator/=(const T &rhs);
    Coords operator+=(const Coords<T> &rhs);
    Coords operator-=(const Coords<T> &rhs);
    Coords operator*=(const Coords<T> &rhs);
    Coords operator/=(const Coords<T> &rhs);
};

This fixes a number of problems with the program: 这解决了该程序的许多问题:

#include <boost/operators.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <vector>
//publicly inherits important boost::operators classes
template <class T>
class Coords: boost::arithmetic<Coords<T>
            ,boost::arithmetic<Coords<T>, T
//              ,boost::indexable<Coords<T>,int,T&
//              ,boost::dereferenceable<Coords<T>, T*>
//            >
    >
>
{
private:
    //private member
    std::vector<T> x_;
public:

    //public constructors
    Coords(int n, T x): x_(n,x){};
    Coords(int n): x_(n){};
    Coords(std::vector<T> &x);
    Coords(const Coords &rhs);

    //iterator nested class, public inherits boost::iterator_facade
    class iterator: public boost::iterator_facade<iterator, T, boost::random_access_traversal_tag >{
        private:
            typename std::vector<T>::iterator iter_;

            friend class boost::iterator_core_access;

            void increment() { ++iter_;}

            void decrement() { --iter_; }

            void advance(int n){ iter_+=n;};

            bool equal(iterator const &other) const{
                return this->iter_ == other.iter_;
            }

            T& dereference() const {return *iter_;};

            int distance_to(iterator const &other) const{
                return this->iter_ - other.iter_;
            }

        public:
            iterator():iter_(0){};

            iterator(const iterator& it):iter_(it.iter_){};
            iterator(iterator& it):iter_(it.iter_){};

            explicit iterator(const typename std::vector<T>::iterator& it):iter_(it){};

    };

    //methods from std::vector I would like to 'copy'
    iterator begin(){return iterator(x_.begin());};
    iterator end(){return iterator(x_.end());};
    iterator operator[](std::size_t n);
    std::size_t size(){return x_.size();};

    //mathematical methods
    T norm() const;
    T square() const;
    T sum() const;
    T dotProd(const Coords &rhs);

    //important operator overloads
    Coords operator+=(const T &rhs);
    Coords operator-=(const T &rhs);
    Coords operator*=(const T &rhs);
    Coords operator/=(const T &rhs);
    Coords operator+=(const Coords<T> &rhs);
    Coords operator-=(const Coords<T> &rhs);
    Coords operator*=(const Coords<T> &rhs);
    Coords operator/=(const Coords<T> &rhs);
};

int main() {
  Coords<int> c(3);
  for(Coords<int>::iterator it(c.begin()); it != c.end(); ++it)
    *it;
}
  • The Boost documentation seems to say that the third template parameter to iterator_facade is a boost:: tag, not an std:: tag. Boost文档似乎说iterator_facade的第三个模板参数是boost::标签,而不是std::标签。
  • The second template parameter to iterator_facade is the value type, not the container type. iterator_facade的第二个模板参数是值类型,而不是容器类型。
  • The code for increment , decrement , and advance all produced (I think ) undefined behavior. 用于incrementdecrementadvance所有产生的(我认为 )未定义行为的代码。
  • When referring to class members from inside the class definition, you don't need to list the class name. 从类定义内部引用类成员时,无需列出类名。 There were several places where Coords<T>:: had to be deleted. 在某些地方,必须删除Coords<T>::

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM