templates:如何使用模板变量控制构造函数args的数量.

Gui*_*nal 17 c++ templates c++11

我试图用这种方式制作一个简单的Vector类(数学):

template <int D, typename T = float>
class Vector
{
  T m[D];
  // ...
};
Run Code Online (Sandbox Code Playgroud)

D维数在哪里.如果是2,则向量将存储两个类型的值T.


如何声明构造函数以获取D类型的参数T

Vector<2> v(1.0f, -6.3f);
Run Code Online (Sandbox Code Playgroud)

D如果特定号码,如何添加功能?我希望添加GetX()if D> = 1,GetY()如果D> = 2且GetZ()if D> = 3,但以下代码应生成编译时错误:

Vector<2> v(1.0f, -6.3f);
cout << v.GetZ() << endl;
Run Code Online (Sandbox Code Playgroud)

如果D <1,如何生成编译时错误?

我没有遵循任何具体的标准,任何事都适合我.

R. *_*des 19

所以我提供了一些人们喜欢的愚蠢答案.但这比那容易:)

template <int D, typename T = float>
class v {
public:
    template <typename... Args>
    v(Args... args) : a{ T(args)... } {
        static_assert(sizeof...(Args) == D, "wrong number of arguments");
    }

private:
    T a[D];
};
Run Code Online (Sandbox Code Playgroud)

您可以使用可变参数模板和SFINAE来获取具有正确数量参数的构造函数.

构造函数没有返回值,因此我们需要在其中一个参数上使用SFINAE.要使用可变参数模板,我们需要在最后使用参数包.

这意味着我们需要在第一个参数上使用SFINAE.

那么这意味着在第一个参数需要比维度少一个参数之后的参数包.

有了这个,我们可以写:

template <int D, typename T>
class v {
public:
    template <typename... Tail>
    v(typename std::enable_if<sizeof...(Tail)+1 == D, T>::type head, Tail... tail)
    : a{ head, T(tail)... } {}

private:
    T a[D];
};
Run Code Online (Sandbox Code Playgroud)

现在:

v<4, int> a(1,2,3,4); // ok!
v<4, int> b(1,2,3);   // error! no such constructor
Run Code Online (Sandbox Code Playgroud)


ron*_*nag 13

我无法访问C++ 11编译器,但也许这样的东西可以工作?

#include <array>
#include <type_traits>

template <int D, typename T>
class Vector
{
    static_assert(D > 0, "Dimension must be greater than 0");
    std::array<T,D> m;
public:
    template<typename... Args>
    Vector(Args&&... args) : m{T(args)...}
    {
         static_assert(sizeof...(Args) == D, "Invalid number of constructor arguments.");
    }

    T GetX() const { return m[0]; }
    T GetY() const { return m[1]; }
    T GetZ() const { return m[2]; }
};

template <typename T>
class Vector<1, T>
{
    std::array<T,1> m;
public:
    Vector(const T& t0) : m{t0}
    {
    }

    T GetX() const { return m[0]; }
};

template <typename T>
class Vector<2, T>
{
    std::array<T,2> m;
public:
    Vector(const T& t0, const T& t1) : m{t0, t1}
    {
    }

    T GetX() const { return m[0]; }
    T GetY() const { return m[1]; }
};
Run Code Online (Sandbox Code Playgroud)


Ker*_* SB 5

这有点偏离主题,但也许它是最少量的工作:使用a tuple.然后你可以免费获得所有的访问者功能.

剩下要做的唯一事情就是建立一个元组工厂:

template <typename T, unsigned int D> struct tuple_maker
{
  typedef typename tcat<T, tuple_maker<T, D - 1>::type>::type type;
}
template <typename T> struct tuple_maker<T, 1>
{
  typedef std::tuple<T> type;
}
Run Code Online (Sandbox Code Playgroud)

我们需要辅助tcat:

template <typename T, typename Tuple> struct tcat;
template <typename T, typename ...Args> struct tcat<T, std::tuple<Args...>>
{
  typedef typename std::tuple<T, Args...> type;
}
Run Code Online (Sandbox Code Playgroud)

用法:

tuple_maker<float, 3>::type myVec3D;
Run Code Online (Sandbox Code Playgroud)

使用模板别名,我们可以做得更好:

template <typename T, unsigned int D>
using MyVector = typename tuple_maker<T, D>::type;

MyVector<double, 4> myVec4D;
Run Code Online (Sandbox Code Playgroud)

  • 难道你不认为谁写了`tuple <int,int,int>*evil = new vector <3,int>;`值得他从中得到什么? (4认同)