小编Jon*_*ann的帖子

C ++ 20协程:实现可期待的未来

由于Coroutines TS在Kona的ISO会议上已被C ++ 20接受,因此我开始自己研究一下它们。Clang已经对协程提供了不错的支持,但是仍然缺乏库支持的实现。特别是,Awaitable类型,如std::futurestd::generator等方面都尚未实现。

因此,我将自己置于std::future等待之中。我主要关注James McNellis在CppCon 2016上的演讲,特别是这张幻灯片:

James McNellis时间戳记37:41上的Screengrab在CppCon 2016上的演讲

这是2019年,实际上我在这张幻灯片上的(可能未经测试?)代码上遇到了一些麻烦:

  • 在我看来,超载operator co_await不再是一回事吗?相反,应该使用可选await_transformpromise_type。不过,不确定我是否正确。
  • thenfuture 的继续按值捕获句柄,但resume成员函数不是const限定的。我通过制作lambda解决了这一问题mutable

另外,在我的libc ++版本中,thenis_ready尚不可用,std::futurestd::experimental::future仍缺少其中的一部分。为了避免与Awaiter打交道并实现将来的延续,我编写了派生的Future类,它是Awaitable和Awaiter。根据我的理解,最终两者都会成立std::future。您可以在Compiler Explorer上看到我的示例。它确实可以编译。

但是,它也确实存在段错误。这发生在await_resume何时get()调用。这实际上不足为奇,因为此时valid()回报false(调用get()UB)。我认为这是因为当then用于继续将来时,原始的将来对象已移入异步将来,从而使旧的将来无效(*this当时await_resume称为,所以在移动之后)。我的实现从这个答案和我在GitHub上找到的代码then大致上受到启发。这些可能并不理想,但是cppreference明确指出了call的后置条件,因此我认为脱离原来的未来是正确的。 valid() == …

c++ future async-await c++20 c++-coroutine

11
推荐指数
1
解决办法
909
查看次数

operator->返回指针的有效性

我正在实现一个二维数组容器(比如boost::multi_array<T,2>,主要用于练习).为了使用双索引表示法(a[i][j]),我引入了一个代理类row_view(const_row_view但我不关心这里的constness),它保留了指向行的开头和结尾的指针.

我还希望能够分别遍历行和行内的元素:

matrix<double> m;
// fill m
for (row_view row : m) {
    for (double& elem : row) {
        // do something with elem
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,matrix<T>::iterator类(用于遍历行)在row_view rv;内部保持私有以跟踪迭代器指向的行.当然,iterator也实现了dereferenciation功能:

  • 因为operator*(),人们通常想要返回一个参考.相反,这里正确的做法似乎返回一个row_view值(即返回私有的副本row_view).这确保了当迭代器前进时,row_view静止指向前一行.(在某种程度上,row_view行为就像参考一样).
  • 因为operator->(),我不太确定.我看到两个选择:

    1. 返回指向row_view迭代器私有的指针:

      row_view* operator->() const { return &rv; }
      
      Run Code Online (Sandbox Code Playgroud)
    2. 返回指向新的指针row_view(私有指针的副本).由于存储生命周期,必须在堆上分配.为了确保清理,我将其包装成unique_ptr:

      std::unique_ptr<row_view> operator->() const {
          return std::unique_ptr<row_view>(new row_view(rv));
      }
      
      Run Code Online (Sandbox Code Playgroud)

显然,2更正确.如果迭代器 …

c++ containers iterator unique-ptr

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

嵌套类作为模板参数

我尝试编写一个自定义STL样式的容器.为简单起见,我们说它是一个列表.我查找了定义这样一个容器的标准方法:

template <typename T, typename A = std::allocator<T> > class mylist;
Run Code Online (Sandbox Code Playgroud)

现在,我想使用嵌套类来管理列表的节点:

(inside mylist)
class node {
    T data;
    node *next;
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,我不需要template在定义之前放置一个说明符,node因为编译器将为mylist<T,A>::node每个mylist模板参数组合实例化单独的类.

但是,现在我需要为类型T本身的数据分配内存,而且还需要为它们的包装器分配内存node.因此,我希望默认模板参数是类型std::allocator<mylist<T>::node>.但是,在那时,mylist尚未声明,编译器可以理解为难过:

error: `mylist' was not declared in this scope
Run Code Online (Sandbox Code Playgroud)

如何解决这个难题?有两个限制:

  • 通常情况下,我会在没有完全声明其内容的情况下声明缺少的类.但是,因为它嵌套在我想要声明的内容中,所以这不是一个选项.
  • 我需要node嵌套,因为它需要访问分配器实例mylist.例如,我已经operator=声明node了许多内存管理递归发生的地方.对于列表而言,这可能是过度的,您可以从内部执行此操作mylist,从而降低nodeon 的参数依赖性A,但这对于我正在实现的数据结构至关重要.

c++ containers templates stl

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

即使我的特征使用相同的特征作为边界,为什么有必要添加多余的特征边界?

我一直在尝试编写一个特征,该特征需要一种类型来实现Add(以及进一步的向量空间的其他操作)及其自身及其引用。下面是一个小例子,说明了我遇到的问题:

use std::ops::Add;

#[derive(Debug)]
struct MyVec<T>(Vec<T>);

impl<'a, 'b, T: Copy + Add> Add<&'a MyVec<T>> for &'b MyVec<T> {
    type Output = MyVec<T::Output>;
    fn add(self, other: &'a MyVec<T>) -> Self::Output {
        /* ... */
    }
}
impl<'a, T: Copy + Add> Add<MyVec<T>> for &'a MyVec<T> {
    /* ... */
}
impl<'a, T: Copy + Add> Add<&'a MyVec<T>> for MyVec<T> {
    /* ... */
}
impl<T: Copy + Add> Add<MyVec<T>> for MyVec<T> {
    /* ... */
}

trait Addable: Add<Self, …
Run Code Online (Sandbox Code Playgroud)

traits rust

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

在Mac OS X上链接Fortran中的LAPACK

我认为这是一个标准的菜鸟问题,但在整个上午搜索网络后,我决定不管怎么说.我在Mac OS 10.9上,我想从Fortran程序中调用LAPACK特征值例程.我有幸在昨天被介绍给Fortran,所以请原谅任何愚蠢的错误.

这是我想要运行的最小例子:

program eigtest
    complex A(3,3)
    real eigs(3)
    A(1,1) = cmplx(1,0)
    A(1,2) = cmplx(0,2)
    A(1,3) = cmplx(3,0)
    A(2,1) = cmplx(0,-2)
    A(2,2) = cmplx(5,0)
    A(2,3) = cmplx(1,-1)
    A(3,1) = cmplx(3,0)
    A(3,2) = cmplx(1,1)
    A(3,3) = cmplx(7,0)
    call heevd(A, eigs)
    write(*,*) eigs
end
Run Code Online (Sandbox Code Playgroud)

我了解到在OS X上,LAPACK是Accelerate框架的一部分,所以我尝试了以下方法:

gfortran -o eigtest -framework accelerate eigtest.f95
Run Code Online (Sandbox Code Playgroud)

但链接器抱怨:

Undefined symbols for architecture x86_64:
  "_heevd_", referenced from:
      _MAIN__ in ccleuVFO.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

macos linker fortran gfortran lapack

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

对 NumPy 数组进行排序并与它一起排列另一个数组

我有两个 numpy 数组,第一个,A是一维的,第二个, B, 在我想到的应用程序中是二维的,但实际上可以有任何维度。的每个索引都B覆盖与 的单个索引相同的范围A

现在,我想排序A(按降序)但想排列每个维度B。从数学上讲,如果P是排序的排列矩阵A,我想B根据 进行变换np.dot(P, np.dot(B, P.T))。例如,考虑这个例子,其中排序恰好对应于颠倒顺序:

In [1]: import numpy as np

In [2]: A = np.array([1,2,3])

In [3]: B = np.random.rand(3,3); B
Out[3]: 
array([[ 0.67402953,  0.45017072,  0.24324747],
       [ 0.40559793,  0.79007712,  0.94247771],
       [ 0.47477422,  0.27599007,  0.13941255]])

In [4]: # desired output:

In [5]: A[::-1]
Out[5]: array([3, 2, 1])

In [6]: B[::-1,::-1]
Out[6]: 
array([[ 0.13941255,  0.27599007,  0.47477422],
       [ …
Run Code Online (Sandbox Code Playgroud)

python sorting numpy

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

条件调用构造函数

假设某些类foo有两个自定义构造函数,比如说foo::foo(bar const &)foo::foo(baz const &).根据某些条件调用任何一种都是好的风格.例如:

bar a;
baz b;
foo my_foo;
if (...) {
    my_foo = foo(a);
} else {
    my_foo = foo(b);
}
Run Code Online (Sandbox Code Playgroud)

将需要foo默认构造(在我想到的具体情况下这不是很明智)并且基本上浪费时间(和内存)来创建(和删除)默认构造的临时对象.由于范围,不能my_foo在if或else块内声明.

另一种方法是使用指针和构造new.这样效率较低(间接,堆分配)并且可能不安全(不保证指针不悬空;需要delete,尽管后者可以通过使用来处理std::unique_ptr).

我找到了一种方法:

foo my_foo = (...) ? foo(a) : foo(b);
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为三元运算符保证是详尽的,因此范围不是问题.

我不是三元运算符的忠实粉丝,可能想在调用ctors之前在条件块中做一些其他的事情.有没有一种优雅的方法来实现传统的if-else语法相同的东西?

c++

3
推荐指数
1
解决办法
323
查看次数

允许哪些表达式作为[_;中的数组长度N N]?

请考虑Rust中的以下最小示例:

const FOOBAR: usize = 3;

trait Foo {
    const BAR: usize;
}

struct Fubar();

impl Foo for Fubar {
    const BAR: usize = 3;
}

struct Baz<T>(T);

trait Qux {
    fn print_bar();
}

impl<T: Foo> Qux for Baz<T> {
    fn print_bar() {
        println!("bar: {}", T::BAR);   // works
        println!("{:?}", [T::BAR; 3]); // works
        println!("{:?}", [1; FOOBAR]); // works
        println!("{:?}", [1; T::BAR]); // this gives an error
    }
}

fn main() {
    Baz::<Fubar>::print_bar();
}
Run Code Online (Sandbox Code Playgroud)

编译器给出以下错误:

error[E0599]: no associated item named `BAR` …
Run Code Online (Sandbox Code Playgroud)

arrays traits rust

3
推荐指数
1
解决办法
190
查看次数