C++ 简单类中的常量整数特征

C++ 简单类中的常量整数特征,c++,typetraits,C++,Typetraits,给定以下简单声明,是否可以给类一个常量整数特性,指定组件的数量(在本例中为2)?Vec3和Vec4将分别有3和4。我只想将其作为编译时常量,以各种方式实例化其他模板。它不必在运行时出现在那里 template<class T> struct Vec2 { typedef T value_type; typedef unsigned index_type; struct { T x, y; }; }; 模板 结构向量2

给定以下简单声明,是否可以给类一个常量整数特性,指定组件的数量(在本例中为2)?Vec3和Vec4将分别有3和4。我只想将其作为编译时常量,以各种方式实例化其他模板。它不必在运行时出现在那里

template<class T>
struct Vec2
{ 
    typedef T value_type;
    typedef unsigned index_type;

    struct 
    {
        T x, y; 
    };
};
模板
结构向量2
{ 
类型定义T值_类型;
typedef无符号索引类型;
结构
{
tx,y;
};
};

标准库中已有两种解决此问题的方法

std::array
是一种固定大小的数组,具有size()成员函数、开始和结束迭代器以及[]运算符

std::tuple
给出了不相交类型的向量,这些类型可以通过索引进行索引:
get(tuple)
或type
get(tuple)

编辑:

这里有一个可能的解决方案:

#include <iostream>
#include <type_traits>
#include <utility>
#include <array>

template<class Type, size_t Size>
struct my_vector
{
    static constexpr size_t num_components = Size;

    template<class...Args, typename = std::enable_if_t< (sizeof...(Args) == Size) > >
    my_vector(Args&&...args) : _data { std::forward<Args>(args)... } {}

    template<size_t I >
    Type get() const {
        return _data[I];
    }

    std::array<Type, Size> _data;
};

template<class Type, size_t Size, size_t I, class VectorType = my_vector<Type, Size>, typename = void>
struct get;
template<class Type, size_t Size, size_t I >
struct get<Type, Size, I, my_vector<Type, Size>, std::enable_if_t<I <= Size> >
{
static Type apply(const my_vector<Type, Size>& v) {
        return v.get<I>();
    }
};

template<class Type, size_t Size>
Type x(const my_vector<Type, Size>& v)
{
    return get<Type, Size, 0, my_vector<Type, Size>>::apply(v);
}

template<class Type, size_t Size>
Type y(const my_vector<Type, Size>& v)
{
    return get<Type, Size, 1, my_vector<Type, Size>>::apply(v);
}

template<class Type, size_t Size>
Type z(const my_vector<Type, Size>& v)
{
    return get<Type, Size, 2, my_vector<Type, Size>>::apply(v);
}

template<size_t I, class Type, size_t Size>
Type more(const my_vector<Type, Size>& v)
{
    return get<Type, Size, I+3, my_vector<Type, Size>>::apply(v);
}


template<class T> using Vec2 = my_vector<T, 2>;
template<class T> using Vec3 = my_vector<T, 3>;
template<class T> using Vec6 = my_vector<T, 6>;

using namespace std;

auto main() -> int
{
    Vec2<int> v2 { 1, 2 };
    Vec3<int> v3 { 1, 2, 3 };
    Vec6<int> v6 { 1, 2, 3, 4, 5, 6 };

    cout << "v2: " << x(v2) << ", " << y(v2) << endl;
    cout << "v3: " << x(v3) << ", " << y(v3) << ", " << z(v3) << endl;
    cout << "v6: "
    << x(v6) << ", " << y(v6) << ", " << z(v6) << ", "
    << more<0>(v6) << ", " << more<1>(v6) << ", " << more<2>(v6)
    << endl;

    return 0;
}

解决方案要求您指定策略,以便准确地执行此操作

// base class to store members
template<size_t N>
struct Coords; 

template<>
struct Coords<2> {
    double x, y; 
}; 

template<>
struct Coords<3> {
    double x, y, z; 
}; 

template<>
struct Coords<4> {
    double x, y, z, w; 
}; 

// members depend on your base class
template<class T, size_t N>
struct Vec : Coords<N>
{
    using num = integral_constant<size_t, N>; 
};
除非您特别想要命名成员样式,否则我建议使用包含所有值的meber,如

double _coords[N]; // N is a compile time constant so you can have arrays
因为这样的解决方案将更具可伸缩性、通用性和更易于编码


PS我用
double
代替
T
来简化示例

最可移植的方法是添加枚举常量:

template<class T> struct Vec2
{
    enum { num_components = 2 };
};
template<class T> struct Vec3
{
    enum { num_components = 3 };
};
模板结构Vec2
{
枚举{num_components=2};
};
模板结构Vec3
{
枚举{num_components=3};
};
然后只要在需要的地方使用
V::num_components


如果你喜欢C++11,那么你也可以使用static const int num_components=2而不是匿名的
enum
,但是如果您需要与旧编译器兼容,那么
enum
习惯用法将为您省去一些麻烦。

您想要
Vec
Vec
。。。?或者
Vec2::num_components
Vec3::num_components
。。。?也许如果你添加了能够利用这个特性的代码,问题就更清楚了。如果可能的话,我想要Vec2::num_组件。只需添加
enum{num_components=2}到类中。这对您来说够了吗?所以,如果我有一个接受T的模板,我仍然可以编写T::num_组件。我感到额头上有一记耳光。是的,就是这样!有时,C++比看起来更简单……我想到了元组,但没有想到STD::数组。不过,目前我有一个并集(与示例不完全相同),因此我可以将它们引用为.x、.y或[0][1]或用于vec4、vec3和单个浮点等。这在某些情况下很有用。@Robinson添加了一个小示例。我将研究它,谢谢。不幸的是,在Visual studio 2015发布之前,我无法获得constexpr,因此目前无法编译它。请将其替换为
enum{num_components=Size;}
。够好了。我能用union替换结构吗?里面有匿名结构,以便将命名成员样式和数组样式结合在一起?或者这是一个非常糟糕的想法?@Robinson这个想法听起来像C语言中的多态性。我不知道你对什么是好主意的标准;这对你更有效吗?无论如何,这不是我的风格,所以我不会这么做。
double _coords[N]; // N is a compile time constant so you can have arrays
template<class T> struct Vec2
{
    enum { num_components = 2 };
};
template<class T> struct Vec3
{
    enum { num_components = 3 };
};