我正在寻找将 aconcurrent_vector从 PPL 库转换为普通 std::vector 的推荐方法。
我有一个函数,它在 a 中返回其结果,std::vector但内部可能使用也可能不使用并行算法。目前我正在使用insert将元素从并发向量复制到法线向量:
#ifdef PARALLEL
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in a parallel algorithm
std::vector<Foo> sv;
sv.insert(sv.begin(), cv.begin(), cv.end());
return sv;
}
#else
std::vector<Foo> Bar() {
std::vector<Foo> sv;
//Fill sv in a sequential algorithm
return sv;
}
#endif
Run Code Online (Sandbox Code Playgroud)
虽然插入操作的性能目前还不是一个真正的问题(与函数体相比),但它似乎没有必要,我想知道是否有更好的解决方案(顺便说一句:Foo是一个不能移动的简单 POD)。
理想情况下我想要有类似的东西
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in a parallel algorithm
return static_cast<std::vector<Foo>>(cv);
}
Run Code Online (Sandbox Code Playgroud)
或者至少
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in …Run Code Online (Sandbox Code Playgroud) 问题现在
这个问题困扰着我,但我无法找到明确的答案:
我绝对愿意做出贡献,但我相信我缺乏足够高质量的东西才能被接受(我不是专业程序员).
推理/背景
到现在为止,我已经看到了几十个库和框架(无论是图形,物理,数学,导航,传感器融合等......)都基本上都是实现了自己的版本
struct Vector2d {
double x,y;
//...
};
/* ...
* operator overloads
*/
Run Code Online (Sandbox Code Playgroud)
和/或它的3D等价物 - 更不用说在我花时间做一个合适的,可重复使用的版本之前我自己实现的所有场合.
显然,这并不困难,我不担心次优的实现,但每次,我想组合两个库或重用来自不同项目的代码,我必须注意将一个版本转换为另一个版本(通过铸造或 - 如果可能 - 文本替换).
既然委员会正在努力扩展c ++ 17的标准库(特别是使用2D图形框架),我真的希望从一开始就将一个共同的2D向量融入所有接口,所以我可以编写例如:
drawLine(transformCoordinates(trackedObject1.estimatePos(),params),
transformCoordinates(trackedObject2.estimatePos(),params));
Run Code Online (Sandbox Code Playgroud)
而不是
MyOwnVec2D t1{trackedObject1.estimatePosX(), trackedObject1.estPosY()};
MyOwnVec2D t2{trackedObject2.estimatePosX(), trackedObject2.estPosY()};
t1 = transformCoordinates(t1,params);
t2 = transformCoordinates(t2,params);
drawLine(t1.x,t1.y,t2.x,t2.y);
Run Code Online (Sandbox Code Playgroud)
这个例子可能有点夸张,但我认为这表明了我的观点.
我知道std::valarray,它已经朝着正确的方向前进,因为它允许标准操作,如加法和乘法,但如果你只需要两个或三个坐标,它就会带来太多的重量.我认为具有固定大小且没有动态内存分配(例如基于std::array)的valarray 将是一个可接受的解决方案,特别是因为它将带有一个简单的迭代器实现,但我个人更喜欢具有x,y(和z)的类成员.
备注:如果这个话题已经讨论过了,我很抱歉(如果没有,我会感到惊讶),但每次我搜索2d向量时,我都会得到结果,std::vector<std::vector<T>>或者如何实现某个转换,但没有关于标准化的主题.
我理解唯一的事情,ISO/C++ 11中允许的信号处理程序是读取或写入一个无锁的原子变量或者volatile sig_atomic_t(我相信,POSIX有点更宽松,允许调用一堆系统函数).
我想知道,如果有任何办法,唤醒正在等待条件变量的线程.就像这样:
#include <mutex>
#include <atomic>
#include <condition_variable>
std::mutex mux;
std::condition_variable cv;
std::atomic_bool doWait{ true };
void signalHandler(int){
doWait = false;
cv.notify_one();
}
int main() {
//register signal handler
//Do some stuff
{//wait until signal arrived
std::unique_lock<std::mutex> ul(mux);
cv.wait(ul, []{return !doWait; });
}
//Do some more stuff
}
Run Code Online (Sandbox Code Playgroud)
其中至少有两个问题:
notify_one()给信号处理程序(如果我错了,请告诉我)doWait和线程进入休眠之间到达,因此它永远不会被唤醒(显然,我无法锁定signalHander中的互斥锁以避免这种情况).到目前为止,我能看到的唯一解决方案是在doWait变量上实现忙等待(可能在每次迭代中休眠几毫秒),这让我觉得非常低效.
请注意,即使我上面的程序只有一个线程,我用多线程标记了我的问题,因为它是关于线程控制原语.如果标准c ++中没有解决方案,我愿意接受使用Linux/POSIX特定功能的解决方案.
VS2015(对于 C++)中是否有选项或(免费)扩展,以便当 Intellisense 自动完成函数名称(在调用站点)时,它还会添加左括号和右括号并将光标设置在它们之间?
有没有办法以 clang 格式缩进 c++11/14 lambda 体?此外,右大括号应与[]
所以我希望它看起来像这样
auto l = []( int max ) -> std::vector<int> {
std::vector<int> v( max );
std::iota( v.begin(), v.end(), 0 );
return v;
};
Run Code Online (Sandbox Code Playgroud)
代替
auto l = []( int max ) -> std::vector<int> {
std::vector<int> v( max );
std::iota( v.begin(), v.end(), 0 );
return v;
};
Run Code Online (Sandbox Code Playgroud) TL; DR: 我能想到的是下面的代码将编译任何C++ 17兼容标准的C++工具链(基于当前的C++ 17的提案)和MSVC未能这样做,是在执行中的错误?
#include <string_view>
struct Foo : std::string_view {};
int main() {
Foo f1{};
Foo f2{};
return f1 == f2;
}
Run Code Online (Sandbox Code Playgroud)
说明:
我有一个派生自std::string_view并且没有实现自己的比较运算符的类,因为std::string_view语义正是我需要的,我也希望它可以与例如a相媲美std::string.
但是,如果我尝试比较该类的两个实例,MSVC 2017会抱怨具有类似转换的多个重载:
example.cpp
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/xlocale(314): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
8 : <source>(8): error C2666: 'std::operator ==': 3 overloads have similar conversions
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/exception(336): note: could be 'bool std::operator ==(const std::exception_ptr &,const std::exception_ptr &) throw()' [found using argument-dependent lookup]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/exception(341): note: …Run Code Online (Sandbox Code Playgroud) 可以说,我有
foo,它将每个列表的一个值作为参数如何创建foos 的可变参数包,使用两个列表元素的笛卡尔积进行参数化?
这就是我的意思:
template<int ...>
struct u_list {};
template<char ...>
struct c_list {};
template<int, char >
struct foo {};
template<class ...>
struct bar {};
using int_vals = u_list<1, 5, 7>;
using char_vals = c_list<-3, 3>;
using result_t = /* magic happens*/
using ref_t = bar<
foo<1, -3>, foo<1, 3>,
foo<5, -3>, foo<5, 3>,
foo<7, -3>, foo<7, 3>
>;
static_assert(std::is_same<result_t, ref_t >::value, "");
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个适用于c ++ 11的解决方案,并且不使用除c ++ 11标准库之外的任何库.我也有我的handroled版本的c ++ 14's index_sequence/ make_index_sequence并且可以提供非类型参数列表作为数组,如果这简化了代码. …
c++ cartesian-product template-meta-programming variadic-templates c++11
我想我在某处读到如果我将nullptr传递给std :: strftime,该函数将返回所需的缓冲区大小.事实上,以下代码在我尝试过的众多Linux系统上运行得非常好(不是在使用VS编译时):
#include <iostream>
#include <ctime>
#include <string>
int main()
{
std::time_t time{};
std::tm const * ltime = std::localtime(&time);
const char * formatString = "%Y-%b-%d";
//allocate buffer of appropriate size
auto requiredSize = 1 + std::strftime(nullptr, 50, formatString, ltime);
std::cout << "Required buffer size:" << requiredSize << "\n";
//Format time to string
std::string buff(requiredSize, ' ');
std::strftime(&buff[0], requiredSize, formatString, ltime);
std::cout << buff << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是,我无法找到我的原始源或任何其他指定此行为的文档.所以我的问题是:
编辑:我添加了C标签,因为我已经看到了相同的C代码相同的结果,至少使用gcc/g ++(或者更确切地说是glibc/libstdc ++)std::strftime可能只是c函数的别名strftime.
我的理解是(除了从VS2015切换到VS2017的明显例外),Microsoft使ABI在每个版本的Visual C++工具链之间进行了重大更改.因此,如果我想分发库的二进制版本,我必须为我想要支持的每个新版本的VS分发一个单独的版本.
现在我的问题是:
如果这是相关的,我会满足于特定于Win10的答案,但我也对所有Windows版本感兴趣,因为(包括)Win7.我感兴趣的VS Studio的版本是VS2013/15/17,并且 - 就任何预测而言 - 将来的版本.
问题:
是否std::atomic<int> a{};初始化a(为零)?
背景:
通常,我希望T a{};要么给出编译时错误,要么确保它a已初始化并可供使用。要么是因为T是基本/类似 POD 的类型,并且关于聚合/零/值/列表初始化的语言规则导致所有内容都初始化为零(我不知道到底是什么),要么是因为调用默认构造函数“通常" 使对象进入可用状态。当然,需要(不仅仅是允许)双重初始化的类是存在的,但似乎相当罕见——特别是在标准库中。
然而,构造函数的文档 std::atomic说
1) 默认构造函数很简单:除了静态和线程局部对象的零初始化之外,不进行任何初始化。std::atomic_init 可以用来完成初始化。
[...]
默认初始化的 std::atomic 不包含 T 对象,其唯一有效用途是 std::atomic_init 的销毁和初始化,请参阅LWG 2334
我读到这个
std::atomic<int> a{};
assert(a.load() == 0);
Run Code Online (Sandbox Code Playgroud)
不仅不能保证,而且实际上是未定义的行为。
如果是这样的话,那么恕我直言,这是使用原子的一个主要陷阱,特别是因为它似乎是在大多数平台上“按预期”工作的 UB 案例之一:https: //godbolt.org/g/二甲基乙二醇二乙醚
编辑:我也不太明白,为什么这“确保与 C 的兼容性”仅仅保证所有位都设置为零会有什么危害?
注意:
我知道我可以写std::atomic<int> a{0}
c++ ×9
c ×2
c++11 ×2
abi ×1
atomic ×1
autocomplete ×1
c++17 ×1
clang-format ×1
concurrency ×1
glibc ×1
intellisense ×1
lambda ×1
linux ×1
ppl ×1
signals ×1
standards ×1
stl ×1
visual-c++ ×1