元编程:使用const数组
metaprogramming : using a const array
我是元编程的新手,在使用选项卡时遇到了与常量相关的问题。
假设我们有几种"类型"。每种类型都有不同的版本,我们将能够处理每种类型的所有vesrion。为此,我们使用一个包含有关类型的标准信息的结构,以及一个包含每个版本信息的数组。
问题是,每种类型的版本数量并不相同。另外,版本号不是很高,所以我不喜欢使用上述表的动态分配。但是,如果我进行静态分配,我需要为结构的每个实例都有一个大小相同的表。这意味着,我必须获得最高版本值,并将其用作数组的大小。
我来了:我想创建一个小的元编程模板,它在编译时提供最高的版本值,这样我就可以有一个固定大小的数组,它肯定会包含每个类型的必要信息。但是我得到了一个编译错误。
这是一个简化的样本代码,可以重现问题(错误随之而来)
#include <stdio.h>
// change values here
#define VERSION_ALPHA 3
#define VERSION_BETA 5
#define VERSION_GAMMA 2
// different available types
enum TYPES
{
T_ALPHA = 0,
T_BETA,
T_GAMMA,
T_COUNT, // number of types
};
// to access versions more easily from code
static const int typeVersions[T_COUNT] =
{
VERSION_ALPHA,
VERSION_BETA,
VERSION_GAMMA
};
// this meta is used to get the highest version values between all types
template<int i>
class HighestVersion
{
private:
// version of type -1
enum
{
PREVIOUS = HighestVersion<i-1>::VALUE
};
public:
// current max value
enum
{
VALUE = (typeVersions[i] > PREVIOUS ? typeVersions[i] : PREVIOUS)
};
};
// first version
template<>
class HighestVersion<0>
{
public:
// current max value
enum
{
VALUE = typeVersions[0]
};
};
// highest version macro
#define HIGHEST_VERSION HighestVersion<T_COUNT>::VALUE
// holds info about a single type
struct TypeInfo
{
char * s_pName; // name of the type as string
unsigned int s_Flags[HIGHEST_VERSION]; // flags for each available version of this type
};
int main()
{
// instanciate
TypeInfo infos[T_COUNT];
// do stuff, set name, load flags....
/*...*/
// for test purpose, print max version value (should print 5 in this situation)
printf("%dn", HIGHEST_VERSION);
}
编译器说:
error C2057: expected constant expression
@线路
VALUE = (typeVersions[i] > PREVIOUS ? typeVersions[i] : PREVIOUS)
和
VALUE = typeVersions[0]
似乎编译器告诉我表的内容不是恒定的。我认为这是因为表被解释为一个指针,在这种情况下它不是常量(所以如果指针改变了,内容就不一样了)。有没有办法纠正这一点,这样我就可以使用脚本了?它将使用户无需手动设置该表的大小。。。
提前感谢:)
我确信这甚至不可能在静态数组中实现
一个可能的替代品是一个特征类:
template<TYPES>
struct typeVersions;
// specializations for each type
template<>
struct typeVersions<T_ALPHA> { static const int version = VERSION_ALPHA; };
template<>
struct typeVersions<T_BETA> { static const int version = VERSION_BETA; };
// etc...
你会这样使用它:
enum {
VALUE = typeVersions<i>::version
};
正如jrok所说,使用静态数组可能无法做到这一点。但也不是如果您有足够的符合C++11编译器。
我看到你正在使用VC++,而且你可能会致力于它,这很遗憾地意味着你现在可能拥有或掌握的唯一完全一致的C++11编译器是VC++2013预览版。如果你可以使用它,那么通过以下程序修改说明的简单可变模板解决方案将适用于你:
#include <stdio.h>
// change values here
#define VERSION_ALPHA 3
#define VERSION_BETA 5
#define VERSION_GAMMA 2
// different available types
enum TYPES
{
T_ALPHA = 0,
T_BETA,
T_GAMMA,
T_COUNT, // number of types
};
template<int ...Versions>
struct versions_list
{
static_assert(sizeof ...(Versions),
"Cannot have 0 versions");
};
template<int Only>
struct versions_list<Only>
{
static const int max = Only;
};
template<int First, int Last>
struct versions_list<First,Last>
{
static const int max = First > Last ? First : Last;
};
template<int First, int Second, int ...Rest>
struct versions_list<First,Second,Rest...>
{
static const int tail_max = versions_list<Second,Rest...>::max;
static const int max = First > tail_max ? First : tail_max;
};
// Update your version list here:
typedef versions_list<VERSION_ALPHA, VERSION_BETA, VERSION_GAMMA> typeVersions;
#define HIGHEST_VERSION typeVersions::max
// holds info about a single type
struct TypeInfo
{
char * s_pName; // name of the type as string
unsigned int s_Flags[HIGHEST_VERSION]; // flags for each available version of this type
};
int main()
{
// instanciate
TypeInfo infos[T_COUNT];
// do stuff, set name, load flags....
/*...*/
// for test purpose, print max version value (should print 5 in this situation)
printf("%dn", HIGHEST_VERSION);
}
HIGHEST_VERSION
宏在这里真的毫无意义:您可以删除它的定义,并用typeVersions::max
替换所有出现的内容。
顺便说一下,如果您真的想在C++程序中使用C的stdio
API,而不是C++iostream
API,严格来说应该使用#include <cstdio>
,而不是#include <stdio.h>
我不确定C样式数组是否可以做到这一点,但如果您有编译器对C++11的支持,请检查我的解决方案:
#include <array>
#include <iostream>
template <int Size, int Indice>
struct HighestValue
{
static int get(std::array<int, Size> checkedArray) {
return std::max(HighestValue<Size, Indice - 1>::get(checkedArray), checkedArray[Indice]);
}
};
template <int Size>
struct HighestValue<Size, 0>
{
static int get(std::array<int, Size> checkedArray) {
return checkedArray[0];
}
};
template<size_t Size>
int checkMax(std::array<int, Size> checkedArray)
{
return HighestValue<Size, Size - 1>::get(checkedArray);
}
int main()
{
std::array<int, 7> test {1, 5, 2, 3, 123, 5, 2};
std::cout << checkMax(test);
}
目前我没有空闲时间玩这个,但我相信它可以进一步改进。
- 使用对const结构的const数组的引用进行构造
- 初始化类中的静态 const 数组 - C++
- 如何定义在编译时数据未知的 const 数组
- 如何使用函数的输出初始化 const 数组结构字段?
- 是否允许使用初始值设定项列表将const数组引用实例化为构造函数参数
- const 数组,用于在数组长度定义中使用其元素或为模板参数提供值
- 如何访问一系列const变量作为const数组
- 如果在执行过程中替换二进制文件,"const"数组是否驻留在内存中?
- 在源文件中定义 const 数组
- 具有成员变量的对象 Const 数组 = 先前索引成员变量的总和
- 在构造函数中初始化const数组
- 在编译时使用基于模板的长度初始化 const 数组
- 传递const数组时的C 误差区分专业
- c++中const数组的平均值模板
- 如何在类中存储const数组
- 为什么 const 数组优先绑定到 const T& 参数而不是 T&& 参数?
- 如何将静态 const 数组声明和初始化为类成员
- 从 constexpr 构造 const 数组
- 静态 const 数组在 MSVC 中动态初始化
- 使用 const 数组元素初始化