1

我是元编程新手,在使用选项卡时遇到了与 const 相关的问题。

假设我们有几种“类型”。每种类型都有不同的版本,我们将能够处理每种类型的所有版本。为此,我们使用一个包含有关类型的标准信息的结构,以及一个包含每个版本信息的数组。

问题是,每种类型没有相同数量的版本。另外,版本号不是很高,所以我不喜欢使用上述表的动态分配。但是如果我进行静态分配,我需要为结构的每个实例创建一个大小相同的表。这意味着,我必须获得最高版本值并将其用作数组的大小。

我来了:我想创建一个小的元编程模板,它在编译时给出最高的版本值,所以我可以有一个固定大小的数组,肯定会包含每种类型的 necerrasy 信息。但我得到一个编译错误。

这是重现问题的简化示例代码(错误随之而来)

#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("%d\n", HIGHEST_VERSION);
}

编译器说:

error C2057: expected constant expression

@线条

VALUE = (typeVersions[i] > PREVIOUS ? typeVersions[i] : PREVIOUS)

VALUE = typeVersions[0]

编译器似乎告诉我表的内容不是恒定的。我认为这是因为该表被解释为在这种情况下不是常量的指针(因此,如果指针更改,则内容不一样)。有没有办法纠正这个问题,以便我可以使用脚本?这将使用户无需手动设置该表的大小......

提前致谢 :)

4

3 回答 3

1

正如 jrok 所说,使用静态数组可能无法做到这一点。但是,如果您有一个完全符合 C++11 的编译器,那么也没有必要为每个类型版本创建一个 trait-specialization。

我看到您正在使用 VC++ 并且您可能已经致力于它,这很遗憾地意味着您可能拥有或现在使用的唯一完全符合 C++11 的编译器是 VC++ 2013 Preview。如果您可以使用它,那么由您的程序的以下修改说明的简单可变参数模板解决方案将适用于您:

#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("%d\n", HIGHEST_VERSION);
}

宏在HIGHEST_VERSION这里真的毫无意义:您可以删除它的定义并将所有出现的地方替换为typeVersions::max.

顺便说一句,如果你真的想stdio在 C++ 程序中使用 C 的 API 而不是 C++ iostreamAPI,那么严格来说你应该使用#include <cstdio>,而不是#include <stdio.h>

于 2013-08-04T11:49:32.717 回答
1

我敢肯定,甚至不可能使用静态数组来完成这项工作。
一个可能的替代方案是 trait 类:

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
};
于 2013-07-24T13:25:14.490 回答
0

我不确定这是否可以使用 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);
}

目前我没有空闲时间玩这个,但我相信它可以进一步改进。

于 2013-07-24T13:51:55.980 回答