小编Vit*_*meo的帖子

从编译时依赖图(DAG)构建异步`future`回调链

我有一个编译时有异步任务的非循环图.DAG显示了任务之间的依赖关系:通过分析它,可以了解哪些任务可以并行运行(在单独的线程中)以及哪些任务需要等待其他任务在它们开始之前完成(依赖关系).

我要生成从DAG回调链,使用boost::future.then(...),when_all(...)延续辅助功能.这一代的结果将是一个函数,当被调用时,它将启动回调链并执行DAG所描述的任务,并行运行尽可能多的任务.

但是,我遇到了麻烦,找到了适用于所有情况的通用算法.

我做了一些图纸,以使问题更容易理解.这是一个图例,它将向您展示图纸中的符号含义:

图例:如何阅读图像.

让我们从一个简单的线性DAG开始:

实施例0:线性DAG.

这种依赖关系图包括三项任务(A,B,和C).C取决于B.B取决于A.这里没有并行性的可能性 - 生成算法会构建类似于此的东西:

boost::future<void> A, B, C, end;

A.then([]
    {
        B.then([]
            {
                C.get();
                end.get();
            });
    });
Run Code Online (Sandbox Code Playgroud)

(请注意,所有代码示例都不是100%有效 - 我忽略了移动语义,转发和lambda捕获.)

有许多方法可以解决这个线性DAG:无论是从结束开始还是从开始开始,构建正确的回调链都是微不足道的.

当引入分支和连接时,事情开始变得更加复杂.

这是一个带有fork/join的DAG:

示例1:带有fork/join的DAG.

很难想到与此DAG匹配的回调链.如果我尝试向后工作,从最后开始,我的推理如下:

  • end取决于BD.(加入)
    • D取决于C.
    • BC依赖A.(叉子)

可能的链看起来像这样:

boost::future<void> …
Run Code Online (Sandbox Code Playgroud)

c++ algorithm multithreading asynchronous future

30
推荐指数
2
解决办法
1955
查看次数

库设计:允许用户在"仅标题"和动态链接之间做出决定?

我创建了几个目前只有标头的 C++库.我的类的接口和实现都写在同一个.hpp文件中.

我最近开始认为这种设计不是很好:

  1. 如果用户想要编译库并动态链接它,他/她就不能.
  2. 更改单行代码需要完全重新编译依赖于库的现有项目.

我真的很喜欢只有头文件库的方面:所有函​​数都可以内联,并且它们非常容易包含在你的项目中 - 不需要编译/链接任何东西,只需要一个简单的#include指令.

是否有可能充分利用两个世界?我的意思是 - 允许用户选择他/她想要如何使用库.它还可以加快开发速度,因为我以"动态链接模式"处理库以避免荒谬的编译时间,并以"仅标题模式"发布我的成品以最大化性能.

第一个逻辑步骤是将接口和实现划分为.hpp.inl文件.

不过,我不确定如何前进.我已经看到很多库将LIBRARY_API宏添加到它们的函数/类声明中 - 可能需要类似的东西来允许用户选择?


我的所有库函数都以inline关键字为前缀,以避免"多个定义......"错误.我假设关键字将被文件中的LIBRARY_INLINE宏替换.inl?宏将解析inline为"仅标题模式",而不是"动态链接模式".

c++ library-design libraries header-only c++11

29
推荐指数
2
解决办法
2687
查看次数

有`decltype(auto)`变量的实际用例吗?

从我的个人经验以及从咨询答案到诸如decltype(auto)有什么用途的问题我可以找到许多有价值的用例decltype(auto)作为函数返回类型占位符

但是,我在努力思考decltype(auto)变量的任何有效(即有用,现实,有价值)用例时都非常费劲。我想到的唯一可能性是存储函数返回的结果以decltype(auto)供以后传播,但auto&&也可以在此使用,这样会更简单。

我什至搜索了我所有的项目和实验,其中391个出现的decltype(auto)都是返回类型的占位符。

那么,变量是否有实际的用例decltype(auto)还是仅当用作返回类型占位符时此功能才有用?


您如何定义“现实”?

我正在寻找一个能提供价值的用例(即,不仅仅是显示功能如何工作的示例)decltype(auto),与诸如auto&&或根本不声明变量的替代方案相比,哪里是最佳选择。

问题域无关紧要,它可能是一些晦涩的元编程极端案例或神秘的功能编程构造。但是,该示例需要使我接受“嘿,这很聪明/很漂亮!” 而使用任何其他功能来达到相同的效果将需要更多样板,或者存在某种缺陷。

c++ auto type-deduction c++14 decltype-auto

27
推荐指数
2
解决办法
541
查看次数

为什么`std :: make_shared`用`-fno-rtti`执行两次单独的分配?

#include <memory>
struct foo { };
int main() { std::make_shared<foo>(); }
Run Code Online (Sandbox Code Playgroud)

由这两个所产生的asssembly g++7clang++5-fno-exceptions -Ofast上面的代码:

  • 包含对单个呼叫operator new,如果-fno-rtti通过.

  • 包含两个单独的呼叫operator new如果-fno-rtti通过.

这可以gcc.godbolt.org (clang++5版本)轻松验证:

以上godbolt链接的屏幕截图与highlighed operator new call

为什么会这样?为什么禁用RTTI会阻止make_shared统一对象控制块分配?

c++ rtti c++11

25
推荐指数
3
解决办法
1393
查看次数

`reinterpret_cast`是一个'T*`到'T(*)[N]`是不确定的行为?

请考虑以下情形:

std::array<int, 8> a;
auto p = reinterpret_cast<int(*)[8]>(a.data());
(*p)[0] = 42;
Run Code Online (Sandbox Code Playgroud)

这是未定义的行为吗?我觉得是这样的.

  • a.data()返回一个int*,不一样的int(*)[8]

  • cppreference上的类型别名规则似乎表明它无效reinterpret_cast

  • 作为程序员,我知道指向的内存位置a.data()是一个8 int对象数组

是否有任何我失踪的规则使这个reinterpret_cast有效?

c++ strict-aliasing language-lawyer reinterpret-cast c++17

25
推荐指数
2
解决办法
1298
查看次数

使用函数参数作为常量表达式的一部分 - gcc vs clang

请考虑以下代码段:

template <bool> struct B { };

template <typename T>
constexpr bool pred(T t) { return true; } 

template <typename T>
auto f(T t) -> decltype(B<pred(t)>{})
{
}
Run Code Online (Sandbox Code Playgroud)
  • clang ++ (trunk)编译代码

  • g ++ (trunk)编译失败,出现以下错误:

    src:7:34: error: template argument 1 is invalid
    auto f(T t) -> decltype(B<pred(t)>{})
                                    ^
    
    src:7:34: error: template argument 1 is invalid
    src:7:34: error: template argument 1 is invalid
    src:7:34: error: template argument 1 is invalid
    src:7:34: error: template argument 1 is invalid
    src:7:34: error: template …
    Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer constant-expression constexpr c++11

24
推荐指数
1
解决办法
478
查看次数

从函数正确传播`decltype(auto)`变量

(这是“ decltype(auto)变量是否有实际用例?的后续文章)

考虑以下情况-我想将一个函数传递f给另一个函数invoke_log_return,该函数将:

  1. 调用f;

  2. 打印一些东西到stdout ;

  3. 返回的结果f,避免不必要的复制/移动并允许复制省略。

请注意,如果f抛出异常,则不应将任何内容打印到stdout。这是我到目前为止的内容:

template <typename F>
decltype(auto) invoke_log_return(F&& f)
{
    decltype(auto) result{std::forward<F>(f)()};
    std::printf("    ...logging here...\n");

    if constexpr(std::is_reference_v<decltype(result)>)
    {
        return decltype(result)(result);
    }
    else
    {
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

让我们考虑各种可能性:

  • f返回prvalue时

    • result 将成为一个对象;

    • invoke_log_return(f)将是一个prvalue(有资格使用复制省略)。

  • f返回左值x值

    • result 将作为参考;

    • invoke_log_return(f)将是一个左值x

您可以在godbolt.org上看到一个测试应用程序。如您所见, …

c++ copy-elision auto c++17 decltype-auto

24
推荐指数
1
解决办法
437
查看次数

将实体与实体组件系统中的系统匹配的有效方式

我正在研究一个面向数据的实体组件系统,其中组件类型和系统签名在编译时是已知的.


一个实体是一个组件的集合体.可以在运行时从实体添加/删除组件.

组件是一个小的逻辑少类.

一个签名是组件类型的编译时间列表.如果实体包含签名所需的所有组件类型,则称该实体与签名匹配.


一个简短的代码示例将向您展示用户语法的外观以及预期用途:

// User-defined component types.
struct Comp0 : ecs::Component { /*...*/ };
struct Comp1 : ecs::Component { /*...*/ };
struct Comp2 : ecs::Component { /*...*/ };
struct Comp3 : ecs::Component { /*...*/ };

// User-defined system signatures.
using Sig0 = ecs::Requires<Comp0>;
using Sig1 = ecs::Requires<Comp1, Comp3>;
using Sig2 = ecs::Requires<Comp1, Comp2, Comp3>;

// Store all components in a compile-time type list.
using MyComps = ecs::ComponentList
<
    Comp0, Comp1, …
Run Code Online (Sandbox Code Playgroud)

c++ optimization performance c++14 entity-component-system

22
推荐指数
3
解决办法
4686
查看次数

最令人烦恼的解析与阵列访问

在查看一些C++ 03代码时,我发现了一个让我感到困惑的最令人烦恼的解析实例:

#include <sstream>
#include <string>

int main(int, char** argv)
{
    std::stringstream ss(std::string(argv[0]));
}
Run Code Online (Sandbox Code Playgroud)

wandbox上的实例

在上面的代码片段中,ss是一个函数的声明,它接受std::string*并返回std::stringstream.

怎么std::string(argv[0])解析为std::string*

直觉上,我认为这argv[0]是明确无误的访问argv.

c++ most-vexing-parse c++03

21
推荐指数
2
解决办法
1283
查看次数

获取终端窗口的大小(行/列)

有没有可靠的方法来获取当前输出终端窗口的列数/行数?

我想在C/C++程序中检索这些数字.

我主要是在寻找GNU/Linux解决方案,但也需要Windows解决方案.

c c++ shell terminal

20
推荐指数
4
解决办法
2万
查看次数