小编Ber*_*ard的帖子

为什么我要在C++中使用.*运算符?

我最近发现C++中存在.*运算符(以及密切相关的->*运算符).(见这个问题.)

起初看起来很整洁,但为什么我会需要这样的东西呢?链接问题中的两个答案提供了可以从直接函数调用中受益的人为例子.

在直接函数调用不方便的情况下,可以使用函数对象,就像可以使用的lambda函数一样std::sort.这消除了间接级别,因此比使用更高效.*.

链接的问题还提到了此示例的简化版本:

struct A {
    int a;
    int b;
};

void set_member(A& obj, int A::* ptr, int val){
    obj.*ptr = val;
}

int main()
{
    A obj;
    set_member(obj, &A::b, 5);
    set_member(obj, &A::a, 7);
    // Both members of obj are now assigned
}
Run Code Online (Sandbox Code Playgroud)

但这样做是非常微不足道的(可能更好的做法,因为它更清洁,并且不会对成员造成不必要的限制A):

struct A {
    int a;
    int b;
};

void set_me(int& out, int val){
    out = val;
}

int main()
{
    A obj;
    set_me(obj.b, …
Run Code Online (Sandbox Code Playgroud)

c++ pointer-to-member

9
推荐指数
2
解决办法
518
查看次数

为什么协程的返回类型必须是可移动构造的?

考虑以下定义invoker类的代码- 协程的最小返回类型。我们显式地删除了类的复制和移动构造函数invoker

#include <coroutine>
#include <cstdlib>
class invoker {
public:
    class invoker_promise {
    public:
        invoker get_return_object() { return invoker{}; }
        auto initial_suspend() { return std::suspend_never{}; }
        auto final_suspend() { return std::suspend_never{}; }
        void return_void() {}
        void unhandled_exception() { std::abort(); }
    };
    using promise_type = invoker_promise;
    invoker() {}
    invoker(const invoker&) = delete;
    invoker& operator=(const invoker&) = delete;
    invoker(invoker&&) = delete;
    invoker& operator=(invoker&&) = delete;
};

invoker f() {
    co_return;
}
Run Code Online (Sandbox Code Playgroud)

代码不能在最新的 GCC (10.1)上编译,它应该完全支持 C++20 协程。

相反,我们收到一个错误,表明需要移动构造函数: …

c++ coroutine c++20

8
推荐指数
1
解决办法
331
查看次数

SVG 字体的新语法是什么?

我在浏览SVG字体在MDN,在那里,所提到<font-face><missing-glyph><hkern><vkern>计提折旧。只有<glyph>不折旧。它没有提及有关指定字体外观属性的推荐方法的任何内容。

W3C的SVG建议,也没有说关于从提的是,一切都在指定SVG字体,除了的另一种方式什么<font-face>可以等效于CSS来实现。它没有为<hkern>或提供任何替代方案<vkern>。我打算创建一个独立的 SVG 文件,不被站点 CSS 修改,所以我想在 SVG 中保留整个字体定义。

那么,这种指定 SVG 字体的晦涩新方法是什么?

fonts svg

7
推荐指数
1
解决办法
1040
查看次数

防止兄弟结构的平等比较

为了代码重用的目的,我有许多派生自同一个基础的结构,但我不想要任何形式的多态.

struct B {
    int field;
    void doStuff() {}
    bool operator==(const B& b) {
        return field == b.field;
    }
};

struct D1 : public B {
    D1(int field) : B{field} {}
};
struct D2 : public B {
    D2(int field) : B{field} {}
};
Run Code Online (Sandbox Code Playgroud)

结构D1D2(以及更类似的结构)派生自B共享公共字段和方法,因此我不需要在每个派生类中复制这些字段和方法.

结构B永远不会被实例化; 我只使用D1和的实例D2.此外,D1并且D2根本不应该彼此互动.从本质上讲,我不希望任何多态行为:D1并且D2,出于所有目的,应该充当不相关的结构.

我希望任何D1与其他D1s 相比较的平等,以及任何D2与其他D2s 相比较的平等.由于D1并且 …

c++ inheritance siblings c++17

7
推荐指数
2
解决办法
164
查看次数

在实践中,无锁原子是否无地址?

Boost.Interprocess是一个很棒的库,可以简化不同进程之间共享内存的使用.它提供互斥锁,条件变量和信号量,允许在从共享内存中写入和读取时进行同步.

但是,在某些情况下,这些(相对)性能密集型同步机制不是必需的 - 原子操作足以满足我的用例,并且可能会提供更好的性能.

不幸的是,Boost.Interprocess似乎没有原子.


C++标准库提供了std::atomic类模板,它封装了操作需要是原子的对象,还具有测试原子操作是否无锁的功能.但它也不要求无锁原子也不需要地址:[atomics.lockfree]/4只是鼓励无锁操作无地址,这与cppreference一致.

我想不出为什么会以非地址方式实现无锁原子的任何理由.在我看来,以无地址的方式实现无锁原子相当容易.

因为在使用原子而不是互斥体(来自Boost.Interprocess)时我会获得显着的性能优势,所以在这里折扣标准兼容性并将std::atomic对象存储在共享内存中似乎很诱人.


这个问题分为两部分:

  1. 在实践中,CPU是否以无地址方式实现无锁原子?(我只关心用于运行现代桌面和移动操作系统的CPU(例如Windows,MacOS,Linux,Android,iOS),但不关心嵌入式系统)
  2. 为什么实现使用无锁地址的无地址原子?

c++ atomic shared-memory lock-free c++17

7
推荐指数
1
解决办法
660
查看次数

从WebWorker同步获取数据?

虽然我理解JavaScript本质上是单线程的,并且通常对这些事情不满意,但我想知道是否有任何方法可以让WebWorker等到主线程提供一些数据而不破坏WebWorker的调用堆栈.

由于这是一个有趣的项目,我可以使用新技术和不能在旧浏览器上可靠运行的东西,我不介意深奥的黑客,只要它们工作.

我考虑过的其他一些解决方案:

  • 在循环中连续轮询LocalStorage,直到预定密钥上有数据.这似乎是有效的,因为即使在循环中轮询时,其他线程的LocalStorage更新应该对当前线程可见,从所有关于LocalStorage的线程安全性的讨论判断并且有多个选项卡写入相同的LocalStorage键.这种方法的缺点是它不是真正"等待",即工作线程仍然消耗在LocalStorage上的全部CPU使用率.虽然LocalStorage通常使用锁实现,但是长时间不能持有LocalStorage锁(锁被释放一次getItemsetItem返回).

  • ECMAScript 6 yield.这在这里不起作用,因为它需要调用堆栈中的所有函数(直到你想要屈服的地方)被标记为生成器函数.我想暂停我的WebWorker的地方有一个包含WebAssembly函数的调用堆栈,它不能标记为生成器函数.

  • IndexedDB的.这不起作用,因为IndexedDB不支持同步请求.

我知道这个类似的问题,但是这个问题专门讨论了这个onmessage事件,并在2012年之前被问到,yield并且引入了WebAssembly.

有没有办法以某种方式模拟WebWorker线程上的锁,否则,它会等到某些数据可用?

javascript locking synchronous web-worker webassembly

6
推荐指数
1
解决办法
1356
查看次数

在标准库中键入trait以获得聚合初始化?

C++标准库必须std::is_constructible<Class, T...>检查是否可以从给定类型构造类作为参数.

例如,如果我有一个MyClass具有构造函数的类MyClass(int, char),那么std::is_constructible<MyClass, int, char>::value将是true.

是否有类似的标准库类型特征,将检查聚合初始化是否有效,即MyClass{int, char}格式良好并返回MyClass

我的用例:

我想编写一个函数模板,std::tuple使用聚合初始化将其转换为(通常是POD)类,具有以下签名:

template <typename Class, typename... T>
inline Class to_struct(std::tuple<T...>&& tp);
Run Code Online (Sandbox Code Playgroud)

为了防止用户使用带有无效的函数Class,我可以static_assert在函数内部编写一个函数来检查给定tp参数是否具有可转换为成员的类型Class.这似乎是一种类型特征is_aggregate_initializable<Class, T...>会派上用场.

我可以推出自己的这个特性的实现,但仅仅是为了获取信息,标准库中有这样的特性我忽略了,还是很快就会成为标准库的一部分?

c++ type-traits aggregate-initialization c++17

6
推荐指数
1
解决办法
285
查看次数

定义一个可以使用多个“后端”之一来实现其需要执行的操作的板条箱的惯用方法是什么?

我正在编写一个 Rust,它包含一些特定于平台的 API 调用(在本例中,用于打开文件选择器)。

在 Linux 上,有两种方法(“后端”)打开文件选择器 - 使用 GTK 或使用 Portal(它们实际上是什么对于这个问题的目的并不重要 - 只需将它们视为两个不同的系统库可以用来打开文件选择器)。通常,选择取决于应用程序开发人员是否想要可移植性 (GTK) 还是“本机”性 (Portal),并且后端的选择会影响我的库需要链接的库(在 build.rs 中指定)。不可能同时使用两者,因为向用户公开的接口是相同的(这就是要点 - 调用我的库的代码不必关心正在使用的后端,而只与系统库之一链接) 。

应该如何编写 Cargo.toml 文件以允许我的库的用户选择他们想要的后端?

在 CMake 中,这通常如下所示:

set(BACKEND "GTK" CACHE STRING "Select the backend (GTK or Portal)")
Run Code Online (Sandbox Code Playgroud)

在 Cargo 中,我们有“功能”。然而,功能只能“启用”或“禁用”,并且从语义上讲,功能似乎意味着有条件地将代码添加到要编译的库中。虽然有一个关于互斥功能的部分,但它看起来非常像黑客,并且其他选项似乎也不理想。

理想情况下,如果其他库依赖于我的库,他们不需要(甚至尝试)选择所需的后端。最终可执行应用程序的开发人员应该是做出决定的人。

rust rust-cargo

6
推荐指数
1
解决办法
142
查看次数

在 PostgreSQL 中将数据从一列移动到另一列

有时,人们可能希望一些数据从一列移动到另一列。通过移动(与复制相反),我的意思是新列在执行操作之前原本为空,而旧列在执行操作后应设置为空。

我有一个这样定义的表:

CREATE TABLE photos(id BIGSERIAL PRIMARY KEY, photo1 BYTEA, photo2 BYTEA);

假设表中有一个条目,其中photo1包含一些数据,并且photo2NULL。我想做一个UPDATE查询,它photo1变成NULLphoto2包含最初在photo1.

我发出以下 SQL 命令(WHERE为简洁起见省略了子句):

UPDATE photos SET photo2 = photo1, photo1 = NULL;

它似乎工作。

我也这样试过:

UPDATE photos SET photo1 = NULL, photo2 = photo1;

它似乎也有效。

但它保证工作吗?具体来说,可以photo1设置为NULL before photo2设置为photo1,从而导致我NULL在两列中结束?

顺便说一句,UPDATE当我的BYTEAs 很大时,这种标准语法似乎效率低下,因为 …

sql postgresql move

5
推荐指数
1
解决办法
3540
查看次数

std::mutex 的 constexpr 构造函数是如何实现的?

在查看 C++ Reference for 时std::mutex,我注意到 for 的构造函数std::mutex被标记为constexpr

起初这令人惊讶,因为我们通常必须进行系统调用(pthread_mutex_init()(POSIX)或CreateMutex()(Windows))来初始化互斥体。然而,经过仔细检查,对于 POSIX,可以使用常量静态PTHREAD_MUTEX_INITIALIZER初始化互斥体(可能作为全局变量),尽管我找不到 Windows 的等效项。

然而,即使 POSIX 的静态初始化是constexpr构造函数背后的原因,但实现中仍然存在各种未解决的问题:

  1. 在 Windows(或许还有其他非 POSIX 系统)上,可能没有静态初始化互斥体的方法。
  2. 在添加C++20 之前,不可能根据编译时是否调用构造函数来拥有不同的代码路径std::is_constant_evaluated(),因此我们没有办法确定是否应该使用PTHREAD_MUTEX_INITIALIZER或。pthread_mutex_init()

那么,如何实现 的constexpr构造函数呢std::mutex

c++ constructor mutex constexpr c++11

5
推荐指数
1
解决办法
596
查看次数