假设我们有std::aligned_storage
的实现。我为alignof
和alignas
运算符定义了两个宏。
#include <iostream>
#include <cstddef>
#define ALIGNOF(x) alignof(x)
#define ALIGNAS(x) alignas(x)
template<std::size_t N, std::size_t Al = ALIGNOF(std::max_align_t)>
struct aligned_storage
{
struct type {
ALIGNAS(Al) unsigned char data[N];
};
};
int main()
{
// first case
std::cout << ALIGNOF(aligned_storage<16>::type); // Works fine
// second case
std::cout << ALIGNOF(aligned_storage<16, 16>::type); // compiler error
}
在第二种情况下,我在问题的标题中得到错误(用Clang编译,与GCC类似的错误)。如果我分别用alignof
和alignas
替换宏,则不会出现错误。 为什么会这样?
在你开始问我为什么要这样做之前 - 原始宏有C ++ 98兼容的代码,例如__alignof
和__attribute__((__aligned__(x)))
,这些代码是特定于编译器的,所以宏是我的只有选择...
修改 因此,根据标记为重复的问题,一组额外的括号将解决问题。
std::cout << ALIGNOF((aligned_storage<16, 16>::type)); // compiler error
它没有。 那么,我该怎么做呢? (满意的问题?)
答案 0 :(得分:18)
C / C ++预处理器不知道任何C / C ++语言结构,它只是具有自己的语法和规则的文本预处理器。根据该语法,以下代码ALIGNOF(aligned_storage<16, 16>::type)
是带有2个参数(ALIGNOF
和aligned_storage<16
)的宏16>::type
的调用,因为括号内有逗号。
我建议您typedef
aligned_storage<16, 16>
并在此宏调用中使用该类型。
答案 1 :(得分:9)
如前所述,宏参数由逗号分隔,这些逗号不在括号内。有一些简单的方法可以解决这个问题,有些方法比其他方法更通用:
使用可变参数宏(或C ++ 98的相应编译器扩展)(live example):
#define ALIGNOF(...) alignof(__VA_ARGS__)
ALIGNOF(aligned_storage<16, 16>::type)
让调用者传递参数个数并将参数包装在额外的括号中(live example):
#define ALIGNOF(n, tuple) alignof(BOOST_PP_TUPLE_ENUM(n, tuple))
ALIGNOF(2 (aligned_storage<16, 16>::type))
让来电者通过&#34;序列&#34; (live example):
#define ALIGNOF(seq) alignof(BOOST_PP_SEQ_ENUM(seq))
ALIGNOF((aligned_storage<16)(16>::type))
如果参数是类型,请使用typedef
(live example):
typedef aligned_storage<16, 16>::type storage_t;
ALIGNOF(storage_t)
请注意,可以通过模板化结构并公开type
成员来在C ++ 11之前创建模板化别名:
template<int N>
struct alias {
typedef typename aligned_storage<N, N>::type type;
};
如果参数可以使用括号,请让调用者将参数括在括号中并直接使用它。 alignof
没有这种情况。