请考虑以下代码:
constexpr const int A = 42;
const int &B = A;
static_assert(&A == &B, "Bug");
constexpr const int &C = B;
static_assert(&A == &C, "Bug");
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
它完全被clang 3.3版所接受,而g ++(SUSE Linux)4.8.1 20130909 [gcc-4_8-branch revision 202388拒绝它:
bug2.cpp:5:1: error: non-constant condition for static assertion
static_assert(&A == &B, "Bug");
^
bug2.cpp:5:1: error: the value of ‘B’ is not usable in a constant expression
bug2.cpp:2:12: note: ‘B’ was not declared ‘constexpr’
const int &B = A;
^
Run Code Online (Sandbox Code Playgroud)
在我看来,海湾合作委员会是正确的(而我当然更喜欢铿锵行为).试图阅读标准我意识到我不够语言律师来决定.任何人都可以证实吗?
我只是想知道......假设我在C++中有一个POD结构.如果我愿意放在static_assert那里,它会破坏这是一个POD的事实吗?
我知道我可以很容易地把它放在其他地方,我只是问,因为我感兴趣,如果我应该或不应该这样做......
换句话说(更具体):
#include <iostream>
#include <type_traits>
struct A
{
void* ptr;
static_assert(sizeof(void*) == 8, "Pointer should have size 8; platform unsupported");
};
int main()
{
// Is it guaranteed that this will evaluate to 'true'?
std::cout << std::is_pod<A>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud) 鉴于此测试计划:
#include <cassert>
#include <string>
#include <type_traits>
const std::string& const_string = "bla";
std::string const & string_const = "blabla";
static_assert(std::is_same<decltype(const_string), decltype(string_const)>::value, "Uhoh");
int main()
{
assert(std::is_same<decltype(const_string), decltype(string_const)>::value);
}
Run Code Online (Sandbox Code Playgroud)
其中断言两种类型在编译时和使用C的断言在运行时是相同的.Clang,MSVC2015和GCC都报告了同样的错误,所以我很确定这是我:
main.cpp:13:49: error: too many arguments provided to function-like macro invocation
assert(std::is_same<decltype(const_string), decltype(string_const)>::value);
^
/usr/include/assert.h:91:10: note: macro 'assert' defined here
# define assert(expr) \
^
Run Code Online (Sandbox Code Playgroud)
我只是没有看到两个论点assert.更重要的是,这些static_assert作品还不错......那么这里发生了什么?
我怎样才能静态断言表达式是一个std::unique_ptr即std::unique_ptr<T>任何T.
static_assert (std::is_pointer<decltype(exp)>()), "not a smart pointer")
Run Code Online (Sandbox Code Playgroud)
以上不起作用.如果没有直接的话,我只对bool()定义了类型的运算符感兴趣.
我有宏执行除法并检查对齐.
#define BYTES_TO_WORDS(x) ((CHECK_ALIGNMENT(x,2)) * ((x) / 2))
Run Code Online (Sandbox Code Playgroud)
我想实现CHECK_ALIGNMENT一个总是返回1的宏,并且如果x不除以2 则触发错误.
宏BYTES_TO_WORDS从不同的上下文调用,有时x用作编译时常量整数表达式,有时x用作整数表达式这是在运行时解决的.
是否可以实现CHECK_ALIGNMENT,static_assert当使用常量表达式调用宏时,它将执行,并且当表达式不是编译时常量时,会检查一些运行时错误?
我可以更改宏定义,但不能更改宏的调用和使用方式.
这是一个可能的解决方案(并不总是有效):
#define CHECK_ALIGNMENT(x,alignedTo) (1/(((alignedTo)-((x)%(alignedTo)))/(alignedTo)))
Run Code Online (Sandbox Code Playgroud)
在此实现中,我们应该在运行时或编译时获得Division By Zero错误,具体取决于输入.
但是,由于编译器错误,这并不总是有效.此外,错误消息不是很好.
一个更好的解决方案是确定参数是否是编译时常量,并static_assert在这种情况下使用,编译时错误消息.如果参数不表示编译时常量,则检查运行时的对齐方式.
这可能吗?
我需要这个在Visual Studio 2015上工作.
关于为什么我在C++问题中使用宏,评论中有一些讨论.
所述BYTES_TO_WORDS宏是其中通过各种工具包括一个头文件,C++编译器是其中之一.
其他工具使用此宏并评估算术表达式((x) / 2),但在这些工具上我定义CHECK_ALIGNMENT为1,因为它们不能处理constexpr,模板甚至函数调用.
当用C++编译器编译这个头时,我想定义CHECK_ALIGNMENT一些其他东西,static_assert在需要时会触发或运行时错误.
定义CHECK_ALIGNMENT可以是任何C++ 11代码(或VS2015支持的C++ 14),可以使用模板,constexpr或诸如此类的东西.
当对编译时 constexpr 的测试评估为真时,是否可以打印消息?像 static_assert 这样的东西而不停止编译器。
constexpr Application::Mode SETUP_MODE = Application::Debug;
// Can I somehow test if the SETUP_MODE is debug for pragma message?
#pragma message("Application mode is set to Debug!")
static_assert(SETUP_MODE != Application::Debug,
"Application mode is set to Debug!"); // Can I somehow just print this message without aborting the compilation?
Run Code Online (Sandbox Code Playgroud) 考虑以下在Clang 3.8上成功编译的问题-std=c++14.
#include <boost/hana.hpp>
namespace hana = boost::hana;
int main() {
constexpr auto indices = hana::range<unsigned, 0, 3>();
hana::for_each(indices, [&](auto i) {
hana::for_each(indices, [&](auto j) {
constexpr bool test = (i == (j == i ? j : i));
static_assert(test, "error");
});
});
}
Run Code Online (Sandbox Code Playgroud)
测试是非常不敏感的,但这不是重点.现在考虑一个替代版本,其中测试直接放在static_assert:
#include <boost/hana.hpp>
namespace hana = boost::hana;
int main() {
constexpr auto indices = hana::range<unsigned, 0, 3>();
hana::for_each(indices, [&](auto i) {
hana::for_each(indices, [&](auto j) {
static_assert((i == (j == i ? j …Run Code Online (Sandbox Code Playgroud) 我想要做的是让一些类从一个extention类继承。问题是extention类必须知道它正在扩展哪个类。
这可以简单地实现如下:
template<typename Self>
class Extention
{
public:
void check() const
{
std::cout << "Extention is valid: "
<< std::boolalpha
<< std::is_base_of<Extention, Self>::value
<< std::endl;
}
};
class Foo : public Extention<Foo> {};
class Bar : public Extention<void> {};
Run Code Online (Sandbox Code Playgroud)
在Foo与Bar类节目好,进一步扩展的不好的用法。
Foo().check(); ? Extention is valid: true
Bar().check(); ? Extention is valid: false
Run Code Online (Sandbox Code Playgroud)
我想在编译时检查模板的有效性,这让我写了
template<typename Self>
class Extention
{
static_assert(std::is_base_of<Extention, Self>::value);
};
Run Code Online (Sandbox Code Playgroud)
但是,gcc 告诉我这static_assert是错误的,因为class Foo类型不完整。
我究竟做错了什么 ?
编辑:我正在使用-std=c++17 …
以下代码编译:
struct Bar
{
struct Foo
{
int v = 0;
};
// If uncomment the following line, both static assert will fail
// static_assert(std::is_default_constructible_v<Foo>);
};
static_assert(std::is_default_constructible_v<Bar::Foo>);
Run Code Online (Sandbox Code Playgroud)
但是如果我取消注释 first static_assert,两者static_assert都会失败。这怎么会发生?
请参阅http://coliru.stacked-crooked.com/a/64e9c020056e37ed 中的代码
c++ static-assert inner-classes default-constructor type-traits
我碰巧发现GCC和Clang在以下代码的编译上有所不同:
struct Foo
{
int mem = 42;
};
int main()
{
constexpr Foo foo;
static_assert(__builtin_constant_p(foo));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用g++ -std=c++17和编译clang++ -std=c++17。
特别是,
g++-9 (Homebrew GCC 9.3.0_1) 9.3.0编译,而Apple clang version 11.0.3 (clang-1103.0.32.62)无法编译,抱怨说error: static_assert failed due to requirement '__builtin_constant_p(foo)'
static_assert(__builtin_constant_p(foo));
^ ~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
我没有发现任何关于__builtin_constant_p.
为了 __builtin_constant_p
您可以使用内置函数 __builtin_constant_p 来确定某个值在编译时是否已知为常量...
叮当 说
Clang 支持许多与 GCC 语法相同的内置库函数,包括 __builtin_nan、__builtin_constant_p、__builtin_choose_expr、__builtin_types_compatible_p、__builtin_assume_aligned、__sync_fetch_and_add 等。
问题:虽然我知道__builtin_constant_p是一个编译器扩展,但哪个应该是正确的?
c++ ×10
static-assert ×10
constexpr ×3
assert ×2
c++11 ×2
clang++ ×2
boost-hana ×1
c++14 ×1
g++ ×1
inheritance ×1
templates ×1
type-traits ×1
types ×1
visual-c++ ×1