C 动态新闻推送 第46期
文章
- 一个variant bug
int main() {
using namespace std;
variant<string, bool> var{"im-a-string"};
if (holds_alternative<string>(var)) {
cout << "string value is: " << get<string>(var) << endl; // GCC > 9.4
} else if (holds_alternative<bool>(var)) {
cout << "bool value is: " << get<bool>(var) << endl; // GCC <= 9.4
} else {
abort();
}
}
在旧的gcc版本会打印bool
主要原因是这个构造语意存在问题p0608r3 这个提案就是解决这个问题
- c tip of week 260 Did you know that C 23 added std::move_only_function?
这个就是c 14-c 17那会社区一直念叨的function_ref function_view,一个轻量的function
代码语言:javascript复制#include <functional>
int main() {
{
std::function<int()> f{[]{return 42; }};
auto copy = f; // okay
auto value = f();
}
{
std::move_only_function<int()> f{[] {return 42; }};
auto copy = f; // error, call to deleted copy constructor
auto value = f(); // undefined behaviour, dandling reference
}
}
终于进c 了,叫move_only_function
- c 20 十个典型代码段
concept限制的auto
代码语言:javascript复制void signedIntsOnly(SignedIntegral auto val) { }
void floatsOnly(std::floating_point auto fp) { }
//等价
template <SignedIntegral T>
void signedIntsOnly(T val) { }
template <std::floating_point T>
void floatsOnly(T fp) { }
比较泛化的lambda
代码语言:javascript复制auto fn = []<typename T>(vector<T> const& vec) {
cout << size(vec) << “, “ << vec.capacity();
};
尽可能的constexpr
代码语言:javascript复制#include <numeric>
constexpr int naiveSum(unsigned int n) {
auto p = new int[n];
std::iota(p, p n, 1);
auto tmp = std::accumulate(p, p n, 0);
delete[] p;
return tmp;
}
constexpr int smartSum(unsigned int n) {
return (1 n)*(n/2);
}
int main() {
static_assert(naiveSum(10) == smartSum(10));
return 0;
}
Using enum 简单化代码
代码语言:javascript复制#include <iostream>
enum class long_enum_name { hello, world, coding };
void func(long_enum_name len) {
#if defined(__cpp_using_enum) // c 20 feature testing
switch (len) {
using enum long_enum_name;
case hello: std::cout << "hello "; break;
case world: std::cout << "world "; break;
case coding: std::cout << "coding "; break;
}
#else
switch (len) {
case long_enum_name::hello: std::cout << "hello "; break;
case long_enum_name::world: std::cout << "world "; break;
case long_enum_name::coding: std::cout << "coding "; break;
}
#endif
}
enum class another_long_name { hello, breaking, code };
int main() {
using enum long_enum_name;
func(hello);
func(coding);
func(world);
// using enum another_long_name; // error: 'another_long_name::hello'
// conflicts with a previous declaration
}
复杂的NTTP (不过很少用得到)
代码语言:javascript复制#include <iostream>
struct Constants {
double gravityAcceleration_ { 1.0 };
constexpr double getGA() const { return gravityAcceleration_;}
};
template <Constants C>
double ComputeWeight(double mass) {
return mass * C.getGA();
}
int main() {
constexpr Constants EarthGa { 9.81 };
constexpr Constants MoonGa { 1.625 };
std::cout << ComputeWeight<EarthGa>(70.0) << 'n';
std::cout << ComputeWeight<MoonGa>(70.0) << 'n';
}
位域初始化
代码语言:javascript复制#include <iostream>
struct Type {
int value : 4 = 1;
int second : 4 { 2 };
};
int main() {
Type t;
std::cout << t.value << 'n';
std::cout << t.second << 'n';
}
c的字段构造
代码语言:javascript复制struct Point { double x; double y; };
Point p { .x = 10.0, .y = 20.0 };
nodiscard带信息
代码语言:javascript复制[[nodiscard("Don't call this heavy function if you don't need the result!")]]
bool Compute();
rangefor结合初始化,这也是之前提到过的range-for的缺陷问题,有了新的解决方案
代码语言:javascript复制//for (init; decl : expr)
for (auto& x : foo().items()) { /* .. */ } // 生命周期问题,不能这么搞
for (T thing = foo(); auto& x : thing.items()) { /* ... */ } // OK
consteval, 深度优化成立即数
代码语言:javascript复制consteval int sum(int a, int b) {
return a b;
}
constexpr int sum_c(int a, int b) {
return a b;
}
int main() {
constexpr auto c = sum(100, 100);
static_assert(c == 200);
constexpr auto val = 10;
static_assert(sum(val, val) == 2*val);
int a = 10;
int b = sum_c(a, 10); // fine with constexpr function
// int d = sum(a, 10); // error! the value of 'a' is
// not usable in a constant expression
}
- Prevent Trojan Source attacks with GCC 12
看这段代码
代码语言:javascript复制int main() {
int isAdmin = 0;
/* } if (isAdmin) begin admins only */
__builtin_printf("You are an admin.n");
/* end admins only { */
return 0;
}
这些特殊字符 gcc12会告警。所以后面的代码不会生效
- C Language Interoperability Layer
讨论c repl交互的进展,一些实现,比如julia cling等等 (这玩意真的有人用吗)
- How we used C 20 to eliminate an entire class of runtime bugs
有了consteval和fmtlib,代码更好写了
以前的代码
代码语言:javascript复制constexpr ErrorToMessage error_to_message[] = {
{ C2000, fetch_message(C2000) },
{ C2001, fetch_message(C2001) },
...
};
template <typename... Ts>
constexpr bool are_arguments_valid(ErrorNumber n) {
/* 1. fetch message
2. parse specifiers
3. check each specifier against the parameter pack Ts... */
return result;
}
template <typename... Ts>
void error(ErrorNumber n, Ts&&... ts) {
assert(are_arguments_valid<Ts...>(n));
/* do error stuff */
}
现在的代码
代码语言:javascript复制#include <string_view>
#include <type_traits>
// Exposition only
#define FAIL_CONSTEVAL throw
template <typename T>
struct Checker {
consteval Checker(const char* fmt) {
if (fmt != std::string_view{ "valid" }) // #1
FAIL_CONSTEVAL;
// T must be an int
if (!std::is_same_v<T, int>) // #2
FAIL_CONSTEVAL;
}
};
template <typename T>
void fmt(std::type_identity_t<Checker<T>> checked, T);
int main() {
fmt("valid", 10); // compiles
fmt("oops", 10); // fails at #1
fmt("valid", "foo"); // fails at #2
}
consteval能编译期就把不合法的使用找出来
视频
- Daniel Withopf - Physical Units for Matrices. How hard can it be? - Meeting C 2021
介绍这个有量纲计算的库https://github.com/mpusz/units 编译期计算
新项目介绍/版本更新
- oatpp 1.3.0发布,一个网络库
- json bugfix
- SObjectizer 一个actor库
- 用 C 14 写了个模糊查找命令行工具
- toml 性能提升30% toml是一种配置文件格式,ini和yaml结合的感觉。rust的cargo包管理用的就是这个格式
[library]
name = "toml "
authors = ["Mark Gillard <mark.gillard@outlook.com.au>"]
[dependencies]
cpp = 17
- SecretHandshake secure connections for Cap’n Proto RPC 一个rpc server 这个协议不知道干嘛的
- self_macro 感觉是一个type map实现,但是不知道有啥用
- veque vector deque 点子有点意思,有点ringbuffer的感觉