我正在编写一个宏,它将声明作为单个参数。是否有可能推断宏中的声明类型而不将单个参数拆分为单独的类型和标识符参数?
#define M(declaration) \
declaration; \
static_assert(sizeof(/* deduce type of 'declaration' */) == 4, "!")
M(int i);
M(double d{3.14});
M(std::string s{"Hello, world!"});
以下实现可行,但感觉用户不太友好(imo):
#define M(type, identifier) \
type identifier; \
static_assert(sizeof(type) == 4, "!")
M(int, i);
M(double, d{3.14});
M(std::string, s{"Hello, world!"});
如果可能的话,我宁愿把声明作为一个论点。
相关问题: Macro to get the type of an expression;但我没能在我的示例中使用该代码(编译器错误:预期的嵌套名称说明符)。
答案 0 :(得分:2)
如果您的静态断言消息非常简单"!"
1 ,我建议您放弃预处理器。让类型系统适合您:
namespace detail {
template<typename T>
struct check_declared_type {
using type = T;
static_assert(sizeof(type) == 4, "!");
};
}
template<typename T>
using M = typename detail::check_declared_type<T>::type;
// .. Later
int main() {
M<int> i;
M<double> d{3.14};
M<std::string> s{"Hello, world!"};
}
<子> 1 - 具体来说,如果您不需要预处理器为您进行任何字符串化。 子>
答案 1 :(得分:1)
这个宏应该适用于你的所有例子,但它确实有一个令人讨厌的问题:
#define M(declaration) \
declaration; \
do { \
struct dummy__ { declaration; }; \
static_assert(sizeof(dummy__) == 4, "!"); \
} while (false)
问题是类定义中的初始化程序必须使用顶级的=
标记或braced-init-list,而不是顶层的括号。因此,例如M(SomeClass obj(true, 3));
将无法编译,即使sizeof(SomeClass)==4
也是如此。由于支撑的初始化器并不完全等同于括号初始化器,这意味着一些声明将无法与宏一起使用。