鉴于以下简单声明,是否可以为类提供一个常量整数特征,指定组件数(在本例中为2)? Vec3和Vec4分别具有3和4。我只想将它作为编译时常量以各种方式实例化其他模板。它不必在运行时存在。
template<class T>
struct Vec2
{
typedef T value_type;
typedef unsigned index_type;
struct
{
T x, y;
};
};
答案 0 :(得分:2)
解决方案可让您指定策略来完全执行
// 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>;
};
现在每种类型都存在以下内容(请注意 num
是一种类型,因此它不占用任何空间):
Vec<2> -> x, y and num::value = 2 (`constexpr` - compile time usable)
Vec<3> -> x, y, z and num::value = 3 //
Vec<4> -> x, y, z, w and num::value = 4 //
除非你特别想要命名成员样式,否则我建议使用包含所有值的meber,例如
double _coords[N]; // N is a compile time constant so you can have arrays
因为这样的解决方案更具可扩展性,通用性且更易于编码。
PS我正在使用double
代替T
来简化示例。
答案 1 :(得分:2)
最便携的方法是添加枚举常量:
template<class T> struct Vec2
{
enum { num_components = 2 };
};
template<class T> struct Vec3
{
enum { num_components = 3 };
};
然后在需要的地方使用V::num_components
。
如果您使用的是C ++ 11,那么您也可以使用static const int num_components = 2;
而不是匿名enum
,但如果您需要与旧编译器兼容,那么enum
成语将会保存你有些头疼。
答案 2 :(得分:1)
标准库中已有两种解决此问题的方法。
std::array<type, size>
是一个固定大小的数组,有一个size()成员函数,begin和end迭代器以及一个[]运算符。
std::tuple<types...>
提供了可以通过索引编制索引的不相交类型的向量:get<i>(tuple)
或类型get<typename>(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;
}
预期产出:
v2: 1, 2
v3: 1, 2, 3
v6: 1, 2, 3, 4, 5, 6