Skip to content

败犬日报 2024-10-18

1. c 如何提供接口让 cpp 传 lambda 进去

提供 void* context, void(*func)(void*) 接口,类似 FunctionRef,有一些 C 库就是这样干的。

示例:

cpp
#include <functional>
#include <iostream>

void registerCallback(void* context, void (*func)(void*)) { func(context); }

struct Content {
    std::function<void()> bind;
    static void call(void* self) { static_cast<Content*>(self)->bind(); }
};

int main() {
    int x = 233;
    auto lambda = [x]() { std::cout << x << std::endl; };
    Content content{lambda};

    registerCallback(&content, Content::call);
    return 0;
}

更进一步,想要消除 function 分配堆内存开销,以及 C 函数内也需要上下文,示例如下:

cpp
#include <iostream>

// C 接口,参数为回调函数和上下文
extern "C" void c_world(void (*func)(void*, void*), void* context) {
    const char* msg = "world";
    func(&msg, context);
}

// 适配 C 接口,允许传入 C++ 仿函数
template <typename Func>
void invoke_c_style(void (*c_func)(void (*)(void*, void*), void*), Func f) {
    auto callback = [](void* data, void* context) {
        auto& func = *static_cast<Func*>(context);
        func(data);
    };
    c_func(callback, &f);
}

int main() {
    std::string message = "Hello, ";
    invoke_c_style(c_world, [&](void* c_msg) {
        std::cout << message << *static_cast<const char**>(c_msg) << "!\n";
    });
}

2. 类外能重载赋值运算符吗

不行。

不行的原因可能是,类有默认的赋值运算符,容易出现歧义。

3. 并行优化好多都在 O3(编译选项)里面

空间优化是 Os。

4. void func(const std::shared_ptr &ptr) 写法好吗

没有明显的缺点。

5. 把 double tostring 再转回来,这个误差会有多大

测试结果看起来就是保留 6 位小数(但是 cppref 没说)。这样的话,数字小相对误差就会很大。

cpp
#include <cstdio>
#include <string>
int main() {
    double d = 0.00000114514;
    printf("%.20f\n", d);
    std::string s = std::to_string(d);
    printf("%s\n", s.c_str());
    d = std::stod(s);
    printf("%.20f\n", d);
    return 0;
}

输出是:

text
0.00000114514000000000
0.000001
0.00000100000000000000