鉴于此宏
#define MAKE_TYPE(_a, _b, _c, _d) ((_a) | ((_b) << 8) | ((_c) << 16) | ((_d) << 24))
我想替换它,以便它需要一个数组[4] 。 所以我可以写MAKE_TYPE(“ABCD”)而不是丑陋的MAKE_TYPE('A','B','C','D')
我在编译时使用它来生成一些常量。
但是,它不喜欢我传递像这样的字符串
#define MAKE_TYPE(s) ((s[3]) | ((s[2]) << 8) | ((s[1]) << 16) | ((s[0]) << 24))
错误:数组引用不能出现在常量表达式
中那不起作用。所以我想我会使用模板元编程
来解决它template< char[4] s > class MAKE_TYPE
{
public:
enum{ RESULT = s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24) };
};
不幸的是,这也行不通。我似乎无法在模板中放置char [4]。 我得到了这些错误:
错误:在's'之前预期'&gt;' 错误:'s'未在此范围内声明 错误:数组引用不能出现在常量表达式
中我该怎么做?
答案 0 :(得分:2)
错误消息表示它的含义:数组不能出现在常量表达式中。
模板表达式必须是常量表达式,因此数组不能出现在模板参数中。
你可以有一个指向数组的指针,但这不是你想要的。
啊,看到限制只有四个字符,您可以使用多字符常量,例如单引号中的'ABCD'
。但是,然后字符的顺序是实现定义的。
您似乎尝试的另一件事是从字符常量生成类本身的名称。如果你将裸字而不是字符文字传递给宏,这是有可能的,但是,实际上并非如此。即使它有点工作,也会非常地狱般的。
答案 1 :(得分:2)
你有没有尝试过更多的括号和/或演员?
#define MAKE_TYPE(s) (int((s)[3]) | (int((s)[2]) << 8) | (int((s)[1]) << 16) | (int((s)[0]) << 24))
这对我有用,我使用的东西非常类似于FourCC代码,我的宏被许多不同的编译器使用。
答案 2 :(得分:0)
如果您知道输入为char *
:
template <class RT> RT MakeType( const char * _arg )
{
return _arg[3] | (_arg[2] << 8) | (_arg[1] << 16) | (_arg[0] << 24);
}
否则:
template <class T, class RT> RT MakeType( const T &B0, const T &B1, const T &B2, const T &B3 )
{
return B3 | (B2 << 8) | (B1 << 16) | (B0 << 24);
}
我愿意:
inline unsigned int MakeType( const char * _arg )
{
return _arg[3] | (_arg[2] << 8) | (_arg[1] << 16) | (_arg[0] << 24);
}
并在必要时施放。
答案 3 :(得分:0)
您可以使用多字符常量,例如int four = 'four'
。行为是特定于编译器的。
答案 4 :(得分:0)
这样的事情怎么样?
template <typename T>
typename boost::enable_if_c<(T('1234')==0x31323334), T>::type
make(T v)
{
return v;
}
const int value = make('ABCD');
这是多字符常量的编译器相关行为的安全网。您可以为不同的编译器行为添加更多实现,根据需要切换字节。这假设'1234'
评估的字节顺序对于每个编译器是一致的。
模板专家可能能够改进。