N4527 5.20 [expr.const] p5
常量表达式是glvalue核心常量表达式,其值指的是一个实体,它是常量表达式的允许结果(如下定义),或者是一个prvalue核心常量表达式,其值是一个对象,对于该对象及其子对象:
- 引用类型的每个非静态数据成员是指一个实体,它是一个常量表达式的允许结果,和
- 如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象的结尾的地址(5.7),函数的地址或空指针值.
如果实体是具有静态存储持续时间的对象,则该实体是常量表达式的允许结果,该对象不是临时对象,或者是其值满足上述约束的临时对象,或者它是函数.
void foo(){
int a = 1;
int b[a || 1]{};//ok in gcc 5.1.0, error in clang 3.8.0
static_assert(a || 1,"");//ok in gcc 5.1.0, error in clang 3.8.0
switch(1){
case a || 1://ok in gcc 5.1.0, error in clang 3.8.0
;
}
}
Run Code Online (Sandbox Code Playgroud)
是a || 1一个不变的表达?
N4527 5.20 [expr.const] p2
条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:
(2.7) - 左值 - 右值转换(4.1),除非适用于
(2.7.1) - 整数或枚举类型的非易失性glvalue,它引用具有前面初始化的完整非易失性const对象,用常量表达式初始化,或者
(2.7.2) - 一个非易失性glvalue,引用字符串文字的子对象(2.13.5),或者
(2.7.3) - 一个非易失性glvalue,引用用constexpr定义的非易失性对象,或引用这种对象的不可变子对象,或者
(2.7.4) - …
P0292R1 constexpr如果已包含在内,正在进行 C++ 17.它似乎很有用(并且可以取代SFINAE的使用),但关于static_assert形成不良的评论,假分支中不需要诊断会让我害怕:
Disarming static_assert declarations in the non-taken branch of a
constexpr if is not proposed.
void f() {
if constexpr (false)
static_assert(false); // ill-formed
}
template<class T>
void g() {
if constexpr (false)
static_assert(false); // ill-formed; no
// diagnostic required for template definition
}
Run Code Online (Sandbox Code Playgroud)
我认为它是完全禁止static_assert在constexpr内部使用if(至少是假/非分支,但实际上这意味着它不是一个安全或有用的事情).
这是如何从标准文本中产生的?我发现static_assert在提案中没有提到措辞,并且C++ 14 constexpr函数允许static_assert(cppreference的详细信息:constexpr).
是否隐藏在这个新句子中(6.4.1之后)?:
当constexpr if语句出现在模板化实体中时,在封闭模板或通用lambda的实例化期间,不会实例化丢弃的语句.
从那以后,我认为它也是禁止的,不需要诊断,调用调用图中某个地方可能调用的其他constexpr(模板)函数static_assert.
底线:
如果我的理解是正确的,那么对于constexpr …
我们正在尝试在C++ 17下测试一些代码并将其更改为std::uncaught_exception.我似乎无法让GCC提供以下价值__cplusplus:
$ /opt/local/bin/g++ -std=c++17 -dM -E - </dev/null | grep __cplusplus
cc1: warning: command line option '-std=c++1z' is valid for C++/ObjC++ but not for C
$
Run Code Online (Sandbox Code Playgroud)
和:
$ /opt/local/bin/g++ --version
g++-mp-6 (MacPorts gcc6 6.1.0_0) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
Run Code Online (Sandbox Code Playgroud)
__cplusplus使用C++ 17时有什么价值?
std::byte是C++ 17中的新类型,它是作为enum class byte : unsigned char.如果没有适当的转换,这将无法使用它.所以,我为这种类型的向量做了一个别名来表示一个字节数组:
using Bytes = std::vector<std::byte>;
Run Code Online (Sandbox Code Playgroud)
但是,它不可能在旧式中使用它:接受它作为参数的函数失败,因为这种类型不能轻易转换为旧std::vector<unsigned char>类型,例如,zipper库的用法:
/resourcecache/pakfile.cpp: In member function 'utils::Bytes resourcecache::PakFile::readFile(const string&)':
/resourcecache/pakfile.cpp:48:52: error: no matching function for call to 'zipper::Unzipper::extractEntryToMemory(const string&, utils::Bytes&)'
unzipper_->extractEntryToMemory(fileName, bytes);
^
In file included from /resourcecache/pakfile.hpp:13:0,
from /resourcecache/pakfile.cpp:1:
/projects/linux/../../thirdparty/zipper/zipper/unzipper.h:31:10: note: candidate: bool zipper::Unzipper::extractEntryToMemory(const string&, std::vector<unsigned char>&)
bool extractEntryToMemory(const std::string& name, std::vector<unsigned char>& vec);
^~~~~~~~~~~~~~~~~~~~
/projects/linux/../../thirdparty/zipper/zipper/unzipper.h:31:10: note: no known conversion for argument 2 from 'utils::Bytes {aka std::vector<std::byte>}' to 'std::vector<unsigned char>&'
Run Code Online (Sandbox Code Playgroud)
我试图表演天真的演员,但这也没有帮助.那么,如果它被设计为有用,它在旧的上下文中是否真的有用?我看到的唯一方法是 …
我一直在 std::string_view 上出现错误曲线,但我能够构建得很好。有没有办法告诉智能感知或 C++ linter 使用 C++17?
我得到的具体错误是:
namespace "std" has no member "string_view"
Run Code Online (Sandbox Code Playgroud) 例如,
#include <iostream>
int main() {
unsigned n{};
std::cin >> n;
std::cout << n << ' ' << (bool)std::cin << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
输入时-1,clang 6.0.0输出,0 0而gcc 7.2.0输出4294967295 1.我想知道谁是对的.或者两者都是正确的标准没有指定这个?如果失败,我认为(bool)std::cin被评估为假.clang 6.0.0也输入失败-0.
这个定义有效:
const auto &b{nullptr};
Run Code Online (Sandbox Code Playgroud)
虽然失败了:
auto *b{nullptr};
Run Code Online (Sandbox Code Playgroud)
我试图在Visual C++,GCC和Clang中编译它.他们都抱怨"不能推断出类型".
在第二种情况下,不b应该推断出有某种类型的std::nullptr_t?
Consider
struct A1 {
constexpr A1& operator=(const A1&) = default;
~A1() {}
};
struct A2 {
constexpr A2& operator=(const A2&) = default;
~A2() = default;
};
struct A3 {
~A3() = default;
constexpr A3& operator=(const A3&) = default;
};
Run Code Online (Sandbox Code Playgroud)
GCC and MSVC accept all three structs. Clang rejects A1 and A2 (but accepts A3), with the following error message:
Run Code Online (Sandbox Code Playgroud)<source>:2:5: error: defaulted definition of copy assignment operator is not constexpr constexpr A1& operator=(const A1&) = default; ^ <source>:6:5: error: …
给定void *一些存储,如何检查它是否指向正确对齐的存储而没有任何实现定义的行为?
我们当然有std::align,但是有更有效的方法吗?
template <std::size_t alignment>
inline bool is_aligned(void * ptr) noexcept {
std::size_t max = 1u;
return std::align(alignment, 1u, ptr, max);
}
Run Code Online (Sandbox Code Playgroud)
PS:我需要以兼容C++标准的方式执行此操作,而不依赖于任何特定于平台的(实现定义的)黑客攻击.
PPS:我为我(理解)英语而道歉,而不是我的母语.
EDIT(2018.08.24):从标题中删除了"有效",添加了更多的措辞,强调我不希望任何实现定义或特定于平台的行为.
如果条件为真,我想在非constexpr时引发编译时错误,例如:
if constexpr(condition1){
...
} else if constexpr (condition2) {
....
} else if constexpr (condition3) {
....
} else {
// I want the else clause never taken. But I heard the code below is not allowed
static_assert(false);
}
// I'd rather not repeat the conditions again like this:
static_assert(condition1 || condition2 || condition3);
Run Code Online (Sandbox Code Playgroud)