显然,无法复制流.应该可以移动流.根据27.9.1.11 [ofstream.cons]段4有可能移动的构造std::ofstream(同为真std::ifstream,std::fstream和std::*stringstream变体).例如:
#include <iostream>
#include <fstream>
#include <string>
std::ofstream makeStream(std::string const& name) {
return std::ofstream(name);
}
int main()
{
std::ofstream out{ makeStream("example.log") };
}
Run Code Online (Sandbox Code Playgroud)
试图运动std::ostream,例如,有一个工厂函数创建一个std::ofstream,一个std::ostringstream,或者根据参数不起作用通过了URN一些其他的流.std::ostream(std::basic_ostream实际上,类模板)protected根据27.7.3.1 [ostream] 有一个移动构造函数.
为什么不能自己std::ostream移动?
我想安全地读一行std::istream.流可以是任何东西,例如,Web服务器上的连接或处理由未知来源提交的文件的东西.有许多答案开始做这个代码的道德等价物:
void read(std::istream& in) {
std::string line;
if (std::getline(in, line)) {
// process the line
}
}
Run Code Online (Sandbox Code Playgroud)
鉴于可能的可疑来源in,使用上述代码会导致漏洞:恶意代理可能会使用巨大的线路对此代码发起拒绝服务攻击.因此,我想将线路长度限制在一个相当高的值,比如4百万char秒.虽然可能会遇到一些大行,但为每个文件分配缓冲区并使用是不可行的std::istream::getline().
如何限制线路的最大尺寸,理想情况下不会过于严重地扭曲代码并且不预先分配大块内存?
C++ 11引入了<random>带有随机数引擎和随机分布声明的头文件.那很好 - 取代那些用途的时间rand()往往会以各种方式出现问题.但是,如何更换它似乎远非显而易见
srand(n);
// ...
int r = rand();
Run Code Online (Sandbox Code Playgroud)
基于声明,似乎可以构建如下的统一分布:
std::default_random_engine engine;
engine.seed(n);
std::uniform_int_distribution<> distribution;
auto rand = [&](){ return distribution(engine); }
Run Code Online (Sandbox Code Playgroud)
这种方法似乎相当复杂,并且肯定是我不记得的东西,不像使用srand()和rand().我知道N4531,但即使这样看起来仍然非常复杂.
是否有一个相当简单的方式来代替srand()和rand()?
在杰克逊维尔会议上,有效采用Parallelism TS规范的提议P0024r2被接受到C++ 17(草案)中.该提议为许多算法添加了重载,这些算法采用执行策略参数来指示应该考虑哪种并行性.在(20.19.2 [执行])中已经定义了三个执行策略:<execution>
std::execution::sequenced_policy(20.19.4 [execpol.seq])带有一个constexpr对象std::execution::seq(20.19.7 [parallel.execpol.objects])来表示顺序执行,类似于在没有执行策略的情况下调用算法.std::execution::parallel_policy(20.19.5 [execpol.par])带有一个constexpr对象std::execution::par(20.19.7 [parallel.execpol.objects]),表示可能使用多个线程执行算法.std::execution::parallel_unsequenced_policy(20.19.6 [execpol.vec])带有一个constexpr对象std::execution::par_unseq(20.19.7 [parallel.execpol.objects]),表示可能使用向量执行和/或多个线程执行算法.STL算法通常将用户定义的对象(迭代器,函数对象)作为参数.用户定义的对象有哪些限制,使它们可以使用标准执行策略与并行算法一起使用?
例如,当使用如下例中的算法时,对FwdItand 的含义是Predicate什么?
template <typename FwdIt, typename Predicate>
FwdIt call_remove_if(FwdIt begin, FwdIt end, Predicate predicate) {
return std::remove_if(std::execution::par, begin, end, predicate);
}
Run Code Online (Sandbox Code Playgroud) 我想实现一些通用算法,我有很多想法,如何根据算法使用的实体的某些特征来实现专门的算法.但是,似乎我没有提出所有特殊特性,我想实现通用版本,以便它们可以与另一个专用版本一起使用.
例如,考虑distance(begin, end)(是的,我知道它在标准库中;但是,它很好很简单,可以用来演示我的问题).一般版本可能看起来像这样(我正在使用std::ptrdiff_t而不是std::iterator_traits<It>::difference_type另一种简化):
template <typename It>
auto distance(It it, It end) -> std::ptrdiff_t {
std::ptrdiff_t size{};
while (it != end) {
++it;
++size;
}
return size;
}
Run Code Online (Sandbox Code Playgroud)
当然,如果迭代器类型是随机访问迭代器,那么使用两个迭代器之间的差异来实现算法要好得多.天真地加入
template <typename It>
auto distance(It begin, It end)
-> typename std::enable_if<is_random_access_v<It>, std::ptrdiff_t>::type {
return end - begin;
}
Run Code Online (Sandbox Code Playgroud)
并不是很有效:两个实现对于随机访问迭代器都是同样好的匹配,即编译器认为它们是不明确的.处理这种情况的简单方法是将一般实现更改为仅适用于非随机访问迭代器.也就是说,SFINAE的选择使得它们相互排斥,同时也覆盖整个空间.
不幸的是,这组实现仍然是关闭的:至少在没有改变签名的情况下,我不能添加另一个实现,以防我对利用特殊属性的泛型实现有另一个想法.例如,如果我想为分段范围添加特殊处理(想法:当基础序列按原样由段组成时,例如,std::deque<...>或者std::istreambuf_iterator<cT>单独处理段的情况),则有必要将一般实现更改为仅适用当序列不是随机访问且它不是分段序列时.当然,如果我控制可以完成的实现.用户将无法扩展通用实现集.
我知道可以为特殊迭代器类型重载函数.但是,这将要求每次添加具有特殊功能的迭代器时,都需要实现相应的功能.目标是允许添加通用实现,这些实现是在它们被使用的实体暴露额外设施的情况下改进的.它类似于不同的迭代器类别,尽管属性与迭代器类别正交.
因此,我的问题是:
有时候只需要一个语句(返回时就必须这样)是方便的,甚至是必要的constexpr.如果需要检查条件并且只允许一个语句,则条件运算符是唯一的选项.如果出现错误,最好从条件运算符中抛出异常,例如:
template <typename It>
typename std::iterator_traits<It>::reference
access(It it, It end) {
return it == end? throw std::runtime_error("no element"): *it;
}
Run Code Online (Sandbox Code Playgroud)
但是,当用作例如(实例)时,上述函数不会编译:
std::vector<int> v;
access(v.begin(), v.end());
Run Code Online (Sandbox Code Playgroud)
编译器抱怨尝试将非const引用绑定到临时.不过,编译器并没有抱怨throw-expression本身.所以问题是:可以从条件运算符抛出异常,如果是这样,上面的代码出了什么问题?
根据ISO网站,新标准被命名为"ISO/IEC 14882:2015 "而不是"ISO/IEC 14882:2014 ".为什么会如此,这会改变吗?例如,有许多标记为C++ 14的东西.
关于如何在使用std :: make_tuple时避免构造函数的未定义执行顺序的问题的答案导致了一个讨论,在此期间我了解到构造函数可以保证参数评估的顺序:使用braced-init-list命令保证从左到右:
T{ a, b, c }
Run Code Online (Sandbox Code Playgroud)
表达式a,b和c,按给定的顺序进行评估.即使类型T只定义了普通的构造函数,也是如此.
显然,并非所有被调用的都是构造函数,有时候在调用函数时保证求值顺序会很好,但是没有像brace-argument-list这样的东西来调用函数,并且定义了对它们的参数的评估顺序.问题变成:构造函数的保证是否可以用于构建函数调用工具(" function_apply()"),并具有用于评估参数的排序保证?要求调用函数对象是可以接受的.
我正忙着测试各种通用算法的实现,而我正在使用对提供的函数支持最少的类型.当使用std::pair<T, movable>某种类型T(例如int)和movable类似定义的类型时,我遇到了这种奇怪的设置:
struct movable
{
movable() {}
movable(movable&&) = default;
// movable(movable const&) = delete;
movable(movable&) = delete;
};
Run Code Online (Sandbox Code Playgroud)
这个想法有一种可移动但不可复制的类型.这很好用,例如,使用这样的表达式:
movable m1 = movable();
movable m2 = std::move(m1);
Run Code Online (Sandbox Code Playgroud)
但是,当尝试使用此类型作为其成员std::pair<...>时失败!为了使代码得到编译,有必要添加deleted(!)复制构造函数来获取movable const&(或只有该版本).采用非const引用的复制构造函数是不够的:
#include <utility>
auto f() -> std::pair<int, movable> {
return std::pair<int, movable>(int(), movable());
}
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?是std::pair<...>通过强制要求overspecified std::pair(std::pair const&)被= default编?
问题似乎std::pair取决于复制构造函数的规范(在20.3.2 [pairs.pair]概要中):
Run Code Online (Sandbox Code Playgroud)namespace std { template <class T1, class T2> …