2

鉴于此宏

#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”之前的预期“>”错误:“s”未在此范围内声明错误:数组引用不能出现在常量表达式中

我该怎么做?

4

5 回答 5

2

错误消息的意思是:数组不能出现在常量表达式中。

模板表达式必须是常量表达式,因此数组不能在模板参数中。

你可以有一个指向数组的指针,但这不是你想要的。

啊,由于限制只有四个字符,您可以使用多字符常量,例如'ABCD'单引号。但是,字符的顺序是实现定义的。

您似乎正在尝试的另一件事是从字符常量生成类本身的名称。如果您将裸字母而不是字符文字传递给宏,这是有可能的,但是,不是真的。即使它有点奏效,那也将是地狱般的。

于 2011-04-07T10:37:39.160 回答
2

您是否尝试过更多的括号和/或强制转换?

#define MAKE_TYPE(s) (int((s)[3]) | (int((s)[2]) << 8) | (int((s)[1]) << 16) | (int((s)[0]) << 24))

这对我有用,我对 FourCC 代码使用了非常相似的东西,并且我的宏被许多不同的编译器使用。

于 2011-04-07T10:48:14.317 回答
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);
}

并在必要时施放。

于 2011-04-07T10:36:50.880 回答
0

您可以使用多字符常量,例如int four = 'four'. 行为是特定于编译器的。

于 2011-04-07T10:42:08.797 回答
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'这假设每个编译器的评估字节顺序是一致的。

模板高手或许可以细化。

于 2011-04-07T13:02:56.030 回答