c++实现我自己的static_assert
C++ implement my own static_assert
作为一个学习项目,我正在编写我自己的模板元编程static_assert。我在网上找到了一个元编程技巧:尝试创建一个大小为0的数组,这将无法编译。所以我使用了两种几乎相同的方法:在Visual Studio上,一种可以工作,另一种不行,但我不明白有什么区别。在c++ 5.4.0中,两者都不能工作(即使使用"-std=c++14"标志)。为什么不呢?
//This correctly aborts the compile on Visual Studio 2015.
//But on g++ it doesn't work (not even with the "-std=c++14" flag) .
template <bool b>
inline void my_static_assert_function()
{
char member[b]; //if b is false, this is 0-length and fails to compile.
}
//On Visual Studio 2015, this does give a warning, but does not
//abort the compile. Why not? It seems virtually identical to the
//previous one. And on g++, it doesn't even warn.
template <bool b>
struct my_static_assert_struct
{
char member[b]; //if b is false, this *warns* but compiles.
};
int main()
{
my_static_assert_function<1 == 2>(); //This aborts the compile, great.
my_static_assert_struct<1 == 2> c; //This does NOT abort the compile???
}
问题#1——为什么"g++ -std=c++14 main.cpp"允许在没有警告的情况下编译它?my_static_assert_function不应该在那里工作吗?我用的是5.4.0版本。
问题#2——在Visual Studio 2015上,my_static_assert_function编译失败,但my_static_assert_struct编译时只给出一个警告。但是有什么区别呢?如果另一个不起作用,一个怎么能起作用呢?
正如@Kerrek SB在评论中提到的,gcc
使用一些非标准的ISO c++扩展来允许零大小的数组,尽管它会给你一个警告。一个更优雅的替代方案是通过std::enable_if
对false
进行SFINAE,就像这样
#include <iostream>
#include <type_traits>
template<bool b, typename std::enable_if<b>::type* = nullptr>
void my_static_assert()
{
std::cout << "Assertion OKn";
}
int main()
{
my_static_assert < (1 < 2) > (); // ok
//my_static_assert < (1 > 2) > (); // fails to compile
}
Live on Coliru
另一种选择(我认为是由Andrei Alexandrescu首先提出的)是保留未定义的泛型模板,并且只定义true
专门化。然后,如果尝试实例化false
专门化,就会得到编译时错误,因为无法实例化不完整类型。在下面的例子:
template<bool> // generic
struct my_static_assert;
template<>
struct my_static_assert<true>{};
int main()
{
my_static_assert < (1 < 2) >{}; // ok
my_static_assert < (1 > 2) >{}; // fails to compile
}
Live on Coliru
好吧,这没有使用模板,但我记得在某处看到过这个:
#define __static_assert(con, id) static int assert_ ## id [2 * !!(con) - 1];
#define _static_assert(con, id) __static_assert(con, id) //expanding any macro that could be in `id` argument
#define static_assert(con) _static_assert(con, __COUNTER__)
解释:
-
!!(con)
使任何非零数字为真(1)和为零变为为假(0) - 通过减去一个得到-1当条件不满足和数组不能有负大小 ->编译时错误
- 我们不希望有多个具有相同名称的数组,为此我们使用
__COUNTER__
宏来组合名称,但为此我们需要首先展开它
相关文章:
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 收到错误"invalid use of non-static data member 'stu::n' "
- LNK1104:无法打开libpjproject-i386-Win32-vc14-Debug-Static.lib
- 我应该在 C++ 中何时/为什么使用 STATIC?
- 在VS2019项目中集成ImageMagick:x64-windows-static library
- 如何在 assert() 和 static_assert() 之间调度,如果在 constexpr 上下文中依赖?
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- 我关于函数"Assert"的C++代码有问题
- "static char __ = []() -> char"的含义
- 当初始值设定项是基类名时'initializer does not name a non-static data member or base class'错误
- 无法在 DLL 中链接 SDL2-static.lib
- 如何摆脱C++中未解析的外部符号"private: static char"错误?
- assert() 在发布模式下充当标识函数吗?
- 如何编写一个接受如下断言消息的自定义断言函数:assert(false) << "assertio
- C++线程"Call to non-static member function without an object argument"
- 出现这种错误的原因是什么"invalid use of non-static data member "
- static是如何使用ClassA::m_variable处理所有类对象的
- LNK2001:未解析的外部符号public:static类std::vector
- static assert - C++ concepts vs static_assert