2011-04-07 61 views
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)) 

错误:一个数组引用不能出现在常数表达式

嘛,没有工作。所以我想我会采用模板metaprogramming

template< char[4] s > class MAKE_TYPE 
{ 
public: 
enum{ RESULT = s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24) }; 
}; 

不幸的是,这也没有奏效。我似乎无法在模板中添加char [4]。 我也得到这些错误:

错误:之前的' 误差预期“>”:“s”的在此范围 错误未声明:数组引用不能出现在恒定表达

我该怎么做?

+1

正如其他人所说,你实际上不能这样做,但是你从模板版本中的错误信息会误导你,因为你已经写了'char [4] s',你的意思是'char s [4]'。它仍然不能解决这个问题,但是你会得到一些错误,告诉你实际的问题是什么,而不是不相关的语法错误:-)。 – 2011-04-07 10:40:44

+1

在'char s [4]'之上,如果你想提供“ABCD”作为名字,它应该读取'char s [5]':) – xtofl 2011-04-07 10:47:37

+0

当然是的,由于null使它成为s [5]。决定以不同的方式解决这个问题。感谢帮助的人。 – Matt 2011-04-07 10:49:10

回答

2

错误消息意味着它说:数组不能出现在常量表达式中。

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

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

啊,看到限制只有四个字符,你可以使用多字符常量,如单引号中的'ABCD'。但是,这些字符的顺序是由实现定义的。

您似乎尝试的另一件事是从字符常量中生成类本身的名称。如果您将粗体字母而不是字符文字传递到宏中,这是可能的,但是,并非如此。即使它有用,它也会非常地狱般。

+0

谢谢,我找到了一个替代解决方案。 – Matt 2011-04-07 10:52:18

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); 
} 

,并投它是否是必要的。

+0

对不起,这是如何工作的?它不需要一个const字符串。 – Matt 2011-04-07 10:43:03

+0

这不会在编译时进行计算。所以这个宏的好处就失去了。 – Naveen 2011-04-07 10:45:12

+0

好 - 但为什么参考? – xtofl 2011-04-07 10:46:22

0

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

2

你有没有尝试过更多的括号和/或演员?

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

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

+0

太棒了!这实际上有效。 – Matt 2011-04-07 10:51:58

+0

对不起,我以为它做了我想要的。原来别人是对的。无法分配给常量。 – Matt 2011-04-07 11:02:22

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'评估的字节顺序是每个编译器一致的。

模板专家可以改进。