template dependent constructor argument lengths

主宰稳场 提交于 2019-12-24 13:54:07

问题


I try to make a generic, but still efficient multi dimension Point class.

What I have is a Dimensions enum

enum Dimension : std::size_t { _2D = 2, _3D = 3 };

And a Point class

template <typename T, Dimension D>
class Point : public std::array<T, D>
{
    public:
        T&        at(size_t idx)       { return std::array<T,D>::at(idx); };
        const T&  at(size_t idx) const { return std::array<T,D>::at(idx); };
        Dimension dim()          const { return D; }
        ...
};

I would like to create nices constructors so I added (outside my class definition)

template <typename T>
Point<T,_2D>::Point(T x, T y)      { at(0) = x; at(1) = y;            }
template <typename T>
Point<T,_3D>::Point(T x, T y, T z) { at(0) = x; at(1) = y; at(2) = z; }

But still I cannot use thoses. The compiler tells me only default (empty) and copy constructors are registered.

Question:

How do I define constructors with arguments list length being dependant on my Dimension template ?


回答1:


There are a few ways to accomplish this. In your case, it might be easiest to use std::enable_if:

template <typename T, Dimension D>
class Point : public std::array<T, D>
{
    public:
        template <
            Dimension D2=D,
            typename = typename std::enable_if<D2==_2D>::type
        >
        Point(T x,T y);

        template <
            Dimension D2=D,
            typename = typename std::enable_if<D2==_3D>::type
        >
        Point(T x,T y,T z);

        T&        at(size_t idx)       { return std::array<T,D>::at(idx); };
        const T&  at(size_t idx) const { return std::array<T,D>::at(idx); };
        Dimension dim()          const { return D; }
        ...
};

Another option would be to break this into multiple classes and use specialization:

template <typename T, Dimension D>
class PointBase : public std::array<T, D>
{
    public:
        T&        at(size_t idx)       { return std::array<T,D>::at(idx); };
        const T&  at(size_t idx) const { return std::array<T,D>::at(idx); };
        Dimension dim()          const { return D; }
        ...
};

template <typename T, Dimension D> class Point;

template <typename T>
class Point<T,_2D> : public PointBase<T,_2D> {
    public:
        Point(T x,T y);
};

template <typename T>
class Point<T,_3D> : public PointBase<T,_3D> {
    public:
        Point(T x,T y,T z);
};



回答2:


I would do it like this because I'm too lazy to write many versions of the same thing:

template<class T, Dimension D>
class Point : public std::array<T,D> {

    template<class... Args>
    Point(Args... vs) :
        std::array<T,D>{{vs...}}
    {
        static_assert(sizeof...(Args) == D, "wrong number of args");
    }

    ...

};


来源:https://stackoverflow.com/questions/27151633/template-dependent-constructor-argument-lengths

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!