C++ 模板 - 简单点类

标签 c++ templates

我正在尝试使用模板(学习)实现一个简单的多维 Point 类。我需要两个特化点 Point2D 和 Point3D - 这是我到目前为止允许构造函数像 Point p (1, 2) 一样直接初始化 Point 的内容。尽管这段代码编译并运行良好,但我不喜欢特化中的代码重复部分——我一定是做错了什么。

我是 C++/模板的新手 - 感谢您的帮助。

#ifndef POINT_H_
#define POINT_H_

template< typename T, int Dimensions = 2 >
class Point
{
public:
    typedef typename T value_type;

    Point() { std::fill(elements_, elements_+Dimensions, 0); }
    Point(const Point<T, Dimensions>& rhs) : elements_(rhs.elements_) {}
    ~Point() {}


    Point & operator=(const Point<T, Dimensions>& rhs) { return *this; }

    const Point operator+(const Point<T, Dimensions>& p)
    {
        Point<T, Dimensions> ret;

        for(int i = 0; i < Dimensions; i++)
        {
            ret[i] += elements_[i] + p[i];
        }

        return ret;
    }

    Point & operator+=( const Point<T, Dimensions>& p)
    {
        for(int i = 0; i < Dimensions; i++)
        {
            elements_[i] += p[i];
        }

        return *this;
    }

    Point & operator-=( const Point<T, Dimensions> & p)
    {
        for(int i = 0; i < Dimensions; i++)
        {
            elements_[i] -= p[i];
        }

        return *this;
    }

    T & operator[](const size_t index)
    {
        return elements_[index];
    }

private:
    T elements_[Dimensions];
};

template<typename T>
class Point< T, 2 >
{
public:
    Point(const T x, const T y)
    {
        elements_[0] = x;
        elements_[1] = y;
    }

    typedef typename T value_type;

    Point() { std::fill(elements_, elements_+Dimensions, 0); }
    Point(const Point<T, 2>& rhs) : elements_(rhs.elements_) {}
    ~Point() {}


    Point & operator=(const Point<T, 2>& rhs) { return *this; }

    const Point operator+(const Point<T, 2>& p)
    {
        Point<T, 2> ret;

        for(int i = 0; i < 2; i++)
        {
            ret[i] += elements_[i] + p[i];
        }

        return ret;
    }

    Point & operator+=( const Point<T, 2>& p)
    {
        for(int i = 0; i < 2; i++)
        {
            elements_[i] += p[i];
        }

        return *this;
    }

    Point & operator-=( const Point<T, 2> & p)
    {
        for(int i = 0; i < 2; i++)
        {
            elements_[i] -= p[i];
        }

        return *this;
    }

    T & operator[](const size_t index)
    {
        return elements_[index];
    }

private:
    T elements_[2];
};


template< typename T>
class Point< T, 3 >
{
public:

    Point(const T x, const T y, const T z)
    {
        elements_[0] = x;
        elements_[1] = y;
        elements_[2] = z;
    }

    typedef typename T value_type;

    Point() { std::fill(elements_, elements_+3, 0); }
    Point(const Point<T, 3>& rhs) : elements_(rhs.elements_) {}
    ~Point() {}


    Point & operator=(const Point<T, 3>& rhs) { return *this; }

    const Point operator+(const Point<T, 3>& p)
    {
        Point<T, 3> ret;

        for(int i = 0; i < 3; i++)
        {
            ret[i] += elements_[i] + p[i];
        }

        return ret;
    }

    Point & operator+=( const Point<T, 3>& p)
    {
        for(int i = 0; i < 3; i++)
        {
            elements_[i] += p[i];
        }

        return *this;
    }

    Point & operator-=( const Point<T, 3> & p)
    {
        for(int i = 0; i < 3; i++)
        {
            elements_[i] -= p[i];
        }

        return *this;
    }

    T & operator[](const size_t index)
    {
        return elements_[index];
    }

private:
    T elements_[3];
};

typedef Point< int, 2 > Point2Di;
typedef Point< int, 3 > Point3Di;


#endif //POINT_H_

最佳答案

您可以 - 简单地 - 在主模板中同时提供 2D 和 3D 构造函数。

没有必要玩弄基类和其他Rube Goldberg solutions在这里,因为没有要解决的问题:我们在模板领域,任何未使用的东西都是未使用的。

例子:

#ifndef POINT_H_
#define POINT_H_

#include <array>            // std::array

#define STATIC_ASSERT( e ) static_assert( e, "!(" #e ")" )

template< typename T, int nDimensions = 2 >
class Point
{
private:
    std::array< T, nDimensions > elements_;

public:
    typedef T ValueType;

    T& operator[]( int const i )
    {
        return elements_[i];
    }

    T const& operator[]( int const i ) const
    {
        return elements_[i];
    }

    void operator+=( Point const& other )
    {
        for( int i = 0; i < nDimensions; ++i )
        {
            elements_[i] += other.elements_[i];
        }
    }

    void operator-=( Point const& other )
    {
        for( int i = 0; i < nDimensions; ++i )
        {
            elements_[i] -= other.elements_[i];
        }
    }

    friend Point operator+( Point const& a, Point const& b )
    {
        Point ret( a );

        ret += b;
        return ret;
    }

    friend Point operator-( Point const&a, Point const& b )
    {
        Point ret( a );

        ret -= b;
        return ret;
    }

    Point(): elements_() {}

    Point( int x, int y )
    {
        STATIC_ASSERT( nDimensions == 2 );
        elements_[0] = x;
        elements_[1] = y;
    }

    Point( int x, int y, int z )
    {
        STATIC_ASSERT( nDimensions == 3 );
        elements_[0] = x;
        elements_[1] = y;
        elements_[2] = z;
    }
};

typedef Point< int, 2 > Point2D;
typedef Point< int, 3 > Point3D;

#endif //POINT_H_

#include <iostream>
using namespace std;

wostream& operator<<( wostream& stream, Point3D const& point )
{
    return (stream << "(" << point[0] << ", " << point[1] << ", " << point[2] << ")");
}

int main()
{
    wcout << "starting" << endl;
    Point3D a( 1, 2, 3 );
    Point3D b( 4, 5, 6 );

    a += b;
    wcout << a << endl;
}

关于C++ 模板 - 简单点类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11891192/

相关文章:

templates - Azure 数据工厂 V2 : auto-start trigger upon deployment?

使用 dowhile 进行 C++ 验证

c++ - 我如何使用和专门化 'curious repeating template pattern'

c++ - 如何使用模板根据类型将元素添加到各种容器

c++ - 数组填充错误

c++ - 使用模板读取 vector

jquery - 在页面模板中使用自定义 jquery

C++ 外部类定义

c++ - 函数返回另一个函数

c++ - 以附加模式打开管道