C++ 使用 static_assert 检查传递给宏的类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4021981/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:18:09  来源:igfitidea点击:

Use static_assert to check types passed to macro

c++cvisual-studio-2010g++static-assert

提问by Matt Joiner

I unfortunately have several macros left over from the original version of my library that employed some pretty crazy C. In particular, I have a series of macros that expect certain types to be passed to them. Is it possible to do something along the lines of:

不幸的是,我的库的原始版本中遗留了几个宏,它们使用了一些非常疯狂的 C。特别是,我有一系列宏希望将某些类型传递给它们。是否可以按照以下方式做一些事情:

static_assert(decltype(retval) == bool);

And how? Are there any clever alternatives?

如何?有什么聪明的选择吗?

Yes I'm aware macros are bad. I'm aware C++ is not C, etc.

是的,我知道宏很糟糕。我知道 C++ 不是 C,等等。

Update0

更新0

Here is some related code, and the source file. Suggestions are welcome. The original question remains the same.

下面是一些相关的代码源文件。欢迎提出建议。最初的问题保持不变。

回答by Matt Joiner

I found this to be the cleanest, using @UncleBenssuggestion:

我发现这是最干净的,使用@ UncleBens建议:

#include <type_traits>

static_assert(std::is_same<decltype(retval), bool>::value, "retval must be bool");

回答by Armen Tsirunyan

Disclaimer: This is a bad answer, there are definitely far better solutions. Just an example :)

免责声明:这是一个糟糕的答案,肯定有更好的解决方案。只是一个例子:)

It is bound to be already implemented, but it's trivial to implement yourself;

肯定是已经实现了,但是自己实现却是小菜一碟;

template <class T1, class T2> struct CheckSameType; //no definition
template <class T> struct CheckSameType<T,T>{}; //

template <class T1, class T2>
AssertHasType(T2)
{
   CheckSameType<T1, T2> tmp; //will result in error if T1 is not T2
}

To be used like this:

像这样使用:

AssertHasType<bool>(retval);

Alternative (suggested by GMan):

替代方案(由 GMan 建议):

template <class T1, class T2> struct SameType
{
    enum{value = false};
}
template <class T> struct SameType<T,T>
{
    enum{value = true};
}; 

To be used like

像这样使用

static_assert(SameType<decltype(retval), bool>::value);

回答by MSalters

It appears you need decltypebecause you've got an expression, but want to verify a type. There are already enough ways to do that now (C++03). For instance, to check a bool

看起来你需要,decltype因为你有一个表达式,但想要验证一个类型。现在已经有足够的方法来做到这一点(C++03)。例如,要检查布尔值

inline void mustBeBool(bool) { }
template<typename T> inline void mustBeBool(T t) { & (&t); } // Takes address of rvalue (&t)

// Use:
#define DifficultMacro(B) do { mustBeBool(B); foo(B); } while (false)

回答by Cheers and hth. - Alf

Most macros can be replaced with inlinefunctions and/or templates. As a case in point, the overly clever argument-size-checking Posix isnanmacro is a template in C++0x. Oh,bad example, but you get the idea.

大多数宏可以替换为inline函数和/或模板。例如,过于聪明的参数大小检查 Posixisnan宏是 C++0x 中的模板。哦,不好的例子,但你明白了。

The main exceptions to that rule are macros that essentially implement higher level languagefeatures. For example, smarter exception handling, or covariance, or a parameterized set of declarations.

该规则的主要例外是本质上实现更高级别语言功能的宏。例如,更智能的异常处理、协方差或一组参数化的声明。

In some cases the macros that can't be reasonable expressed as inlinefunctions or templates, can be replaced with a smarter kind of preprocessing, namely code generation. Then you have a script somewhere that generates the necessary code. For example, it's possible to do options classes in pure C++ with macros and templates, but it's hairy, and as an easier-to-grok and perhaps more maintainable alternative one might use a script that generates the requisite classes, at the cost of extra build steps and dealing with multiple languages.

在某些情况下,不能合理表达为inline函数或模板的宏可以用一种更智能的预处理代替,即代码生成。然后你在某处有一个脚本来生成必要的代码。例如,可以使用宏和模板在纯 C++ 中执行选项类,但它很麻烦,并且作为一种更容易理解且可能更易于维护的替代方案,可以使用生成必需类的脚本,但需要付出额外的代价构建步骤并处理多种语言。

Cheers & hth.,

干杯 & hth.,

回答by Gabriel Staples

If you DO care about the constand volatilequalifiers, and want to ensure the constand volatileparts of the types also exactly match the type you are comparing against, do like @Matt Joiner says:

如果您确实关心constvolatile限定符,并希望确保类型的constvolatile部分也与您要比较的类型完全匹配,请像@Matt Joiner 说的那样

#include <type_traits>

static_assert(std::is_same<decltype(my_variable), uint64_t>::value, 
              "type must be `uint64_t`"); 

I you do NOT care about const, however, and want to simply ensure the type is a certain type without regard for const, do the following instead. Note that std::remove_const<>::typeis required here:

const但是,我不关心,并且只想确保类型是某种类型而不考虑const,请改为执行以下操作。请注意,std::remove_const<>::type这里需要:

static_assert(std::is_same<std::remove_const<decltype(my_variable)>::type, uint64_t>::value, 
              "type must be `uint64_t` OR `const uint64_t`");   

The same goes for volatile. In case you don't care about the volatilepart of the type either, you can ignore it with std::remove_volatile<>::type:

也是如此volatile。如果您也不关心volatile类型的部分,您可以使用以下命令忽略它std::remove_volatile<>::type

static_assert(std::is_same<std::remove_volatile<decltype(my_variable)>::type, uint64_t>::value, 
              "type must be `uint64_t` OR `volatile uint64_t`");

If you don't care about constOR volatile, you can remove them both with std::remove_cv<>::type:

如果您不关心constOR volatile,则可以使用以下命令删除它们std::remove_cv<>::type

static_assert(std::is_same<std::remove_cv<decltype(my_variable)>::type, uint64_t>::value, 
              "type must be `uint64_t` OR `const uint64_t` OR `volatile uint64_t` OR `volatile const uint64_t`");

References:

参考:

  1. Use static_assert to check types passed to macro
  2. https://en.cppreference.com/w/cpp/types/is_same
  3. https://en.cppreference.com/w/cpp/language/decltype
  4. https://en.cppreference.com/w/cpp/header/type_traits
  5. https://en.cppreference.com/w/cpp/types/remove_cv- std::remove_cv<>, std::remove_const<>, std::remove_volatile<>
  1. 使用 static_assert 检查传递给宏的类型
  2. https://en.cppreference.com/w/cpp/types/is_same
  3. https://en.cppreference.com/w/cpp/language/decltype
  4. https://en.cppreference.com/w/cpp/header/type_traits
  5. https://en.cppreference.com/w/cpp/types/remove_cv- std::remove_cv<>, std::remove_const<>,std::remove_volatile<>

Related:

有关的:

  1. Static assert in C[my own answer]
  2. How to use static assert in C to check the types of parameters passed to a macro[my own question]
  3. Typechecking macro arguments in C
  4. *****C++ Limit template type to numbers
  1. C中的静态断言[我自己的答案]
  2. 如何在C中使用静态断言检查传递给宏的参数类型[我自己的问题]
  3. C 中的类型检查宏参数
  4. ***** C++ 将模板类型限制为数字