我有一些我正在使用的库代码.
它在Visual Studio(2008)下编译和工作,但不是GCC(v4.8.4.)
在标题中我们有:
extern const char menu_styles[MENU_COUNT][MAX_LEN];
typedef SysEnum <s_type_t, c_long, no_style, un_style, MAX_LEN, (char *)&menu_styles> MenuStyleEnum;
SysEnum的位置(在另一个文件中定义):
template<class ETYPE, class BTYPE, int MINV, int MAXV, int MLEN, char* pStr> class SysEnum
和gcc borks错误:
error: ‘menu_styles’ cannot appear in a constant-expression
我完全赞同. (此外,它是const char * cast to char *).
我希望VS2008只使用const char *而不是menu_styles来编译这个typedef,但我真的不确定.
我担心VisualSudio会添加某种类似构造函数的代码,因此无论何时使用此typedef,此char *确实指向menu_styles.
在使用GCC进行编译时,我可以用什么来交换它?
最佳答案 你的问题归结为编译
extern const char menu_styles[MENU_COUNT][MAX_LEN];
template<const char* pStr> class SysEnum{
...
};
typedef SysEnum <???> MenuStyleEnum;
我将模板参数更改为const char *,因为否则你必须抛弃constness并且这不是很好的事情.基本上问题是什么???应该.
定义char *模板参数的最常用方法是在某处使用char []变量,这将变为char *使每个人都满意:
extern const char menu_style0[MAX_LEN];
typedef SysEnum <menu_style0> MenuStyleEnum;//compiles...
但是,正如评论中已经指出的那样,该标准不允许我们执行以下任何操作:
typedef SysEnum <menu_styles[0]> MenuStyleEnum;
typedef SysEnum <*menu_styles> MenuStyleEnum;
typedef SysEnum <static_cast<const char *>(&menu_styles)> MenuStyleEnum;
我不确定技术限制是否是这种行为的原因,毕竟在编译时可以找出menu_styles [0]的地址(并且VS就是这样).我的猜测是它不会编译,因为标准是这样说的.
这不会让你有很多选择.如果SysEnum仅使用pStr指向的值(代码如cout<< pStr)并且地址本身并不重要(对于像pStr == otherCharPointer这样的代码就是这种情况),那么下面的解决方法可能是可能性:
#define _MENU_STYLE0_ "STYLE0"
...
extern const char menu_style0[MAX_LEN]= _MENU_STYLE0_;
...
extern const char menu_styles[MENU_COUNT][MAX_LEN]={ _MENU_STYLE0_, _MENU_STYLE1_, ...};
...
typedef SysEnum <menu_style0> MenuStyleEnum;//compiles!
缺点是,menu_styleX和menu_styles中存在相同的信息,这不是一个很好的解决方案.
如果menu_styles中的值只能是模板参数,则可以更容易声明:
template<size_t Index> class SysEnum{
//use menu_styles[index] for pStr
};
typedef SysEnum <0> MenuStyleEnum;
但是,除了存储在menu_styles中之外,您将失去使用值的可能性,并且需要在SysEnum中进行一些重构.