推断声明的类型

Deduce the type of a declaration

本文关键字:类型 声明      更新时间:2023-10-16

我正在编写一个将声明作为其单个参数的宏。是否可以在不将单个参数拆分为单独的类型和标识符参数的情况下推断宏内声明的类型

#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!"});

如果可能的话,我宁愿将声明作为一个单一的论点。


相关问题:宏来获取表达式的类型;但我未能使该代码在我的示例中工作(编译器错误:预期的嵌套名称说明符)。

如果你的静态断言消息真的那么简单"!" 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 - 具体来说,如果您不需要预处理器为您字符串化任何内容。

这个宏应该适用于你的所有例子,但它确实有一个令人讨厌的问题:

#define M(declaration) 
    declaration;       
    do { 
        struct dummy__ { declaration; }; 
        static_assert(sizeof(dummy__) == 4, "!"); 
    } while (false)

问题在于,类定义中的初始值设定项必须在顶级使用 = 标记或大括号 init-list,而不是在顶层使用括号。 因此,例如M(SomeClass obj(true, 3));不会编译,即使sizeof(SomeClass)==4. 由于大括号初始值设定项不完全等同于括号初始值设定项,这意味着某些声明将无法与宏一起使用。