我在许多Python程序中都使用了yield,在很多情况下它确实清除了代码.我在博客上写了这篇文章,这是我网站的热门网页之一.
C#还提供了收益 - 它通过调用者端的状态保持来实现,通过自动生成的类来完成,该类保持状态,函数的局部变量等.
我目前正在阅读有关C++ 0x及其添加的内容; 在阅读有关C++ 0x中lambda的实现时,我发现它也是通过自动生成的类完成的,配备了存储lambda代码的operator().我心中形成了一个自然的问题:他们是为lambdas做过的,他们为什么不考虑支持"收益"呢?
当然,他们可以看到合作例程的价值......所以我只能猜测他们认为基于宏的实现(例如Simon Tatham的)是一个充分的替代品.然而,它们不是出于多种原因:被调用者保持状态,非重入状态,基于宏观(仅此一点是足够的理由)等.
编辑: yield不依赖于垃圾收集,线程或光纤.您可以阅读Simon的文章,看看我在谈论编译器进行简单的转换,例如:
int fibonacci() {
int a = 0, b = 1;
while (true) {
yield a;
int c = a + b;
a = b;
b = c;
}
}
Run Code Online (Sandbox Code Playgroud)
成:
struct GeneratedFibonacci {
int state;
int a, b;
GeneratedFibonacci() : state (0), a (0), b (1) {}
int operator()() {
switch (state) {
case 0:
state = 1;
while (true) { …Run Code Online (Sandbox Code Playgroud) 在杰克逊维尔会议上,有效采用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) 我正在尝试/std:c++17使用CMake 将编译器标志添加到VS2017.到目前为止,我正在使用"现代"的跨平台方式:
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # -std=c++11 instead of -std=gnu++11
set(MY_CXX_COMPILE_FEATURES cxx_generic_lambdas cxx_range_for cxx_strong_enums)
add_library(mylib INTERFACE)
target_compile_features(mylib INTERFACE ${MY_CXX_COMPILE_FEATURES})
Run Code Online (Sandbox Code Playgroud)
这增加/std:c++14了VS2017(无论如何可能是默认值?).但是我无法将其切换到C++ 17(即添加它/std:c++17).如果我只是手动添加它,我会收到不太好的警告,因为两个标志都存在:
1>cl : Command line warning D9025: overriding '/std:c++14' with '/std:c++17'
我已经尝试set(CMAKE_CXX_STANDARD 17)但它没有效果,事实上CMake文档提到CMAKE_CXX_STANDARD对VS无影响.
至于添加C++ 17功能target_compile_features,它似乎还没有(甚至在CMake-3.9.0-rc5中),即使有,我特别只使用std::optionalC++ 17 ,并没有target_compile_features像图书馆功能的标志std::optional.
所以我的问题是,使用CMake做到这一点的最好(或最不丑陋)的方法是什么?在某种程度上它也适用于gcc和clang?我很高兴使用最近的CMake版本(3.8或3.9).我更喜欢它是"好"而不是手动循环通过CXX_COMPILE_FLAGS并删除字符串"/ std:c ++ 14"或类似的一些黑客.
(编辑:它也可以是VS /std:c++latest开关 - 以可能的为准.两者都可以用于此目的.)
许多人使用C++ 17/boost变体的模式看起来与switch语句非常相似.例如:( 来自cppreference.com的片段)
std::variant<int, long, double, std::string> v = ...;
std::visit(overloaded {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
}, v);
Run Code Online (Sandbox Code Playgroud)
问题是当您在访问者中输入错误的类型或更改变体签名时,但忘记更改访问者.您将获得错误的lambda,通常是默认的lambda,而不是获得编译错误,或者您可能会得到一个您没有计划的隐式转换.例如:
v = 2.2;
std::visit(overloaded {
[](auto arg) { std::cout << arg << ' '; },
[](float arg) { std::cout << std::fixed << arg << ' '; } // oops, this won't …Run Code Online (Sandbox Code Playgroud) 这个答案提出了以下问题。
假设我们有一个简单的
struct S {
int& i;
}
Run Code Online (Sandbox Code Playgroud)
内部(至少在 GCC 和 Clang 中)S只包含一个指向 an 的指针int,并且
static_assert(sizeof(int*) == 8);
static_assert(sizeof(S) == 8);
Run Code Online (Sandbox Code Playgroud)
是否S有唯一的对象表示?GCC 和 Clang 不同意 *:
static_assert( std::has_unique_object_representations_v<int*>);
static_assert(!std::has_unique_object_representations_v<S>); // GCC
static_assert( std::has_unique_object_representations_v<S>); // Clang
Run Code Online (Sandbox Code Playgroud)
哪个编译器就在这里,为什么?
* idclev 463035818指出 GCC 和 Clang 之间存在分歧。
我正在尝试使用 C++17if constexpr进行条件编译,但它的行为并不符合我的预期。
比如下面的代码,C++还是编译宏定义的代码X2,
#include <map>
#include <string>
#include <iostream>
#include <type_traits>
#define X1 pp("x")
#define X2 pp("x", "x")
void pp(const std::string str)
{
std::cout << str << std::endl;
}
int main()
{
std::map<std::string, int> map;
if constexpr (std::is_null_pointer_v<decltype(map)>)
X2;
else
X1;
}
Run Code Online (Sandbox Code Playgroud)
并吐出此错误消息:
#include <map>
#include <string>
#include <iostream>
#include <type_traits>
#define X1 pp("x")
#define X2 pp("x", "x")
void pp(const std::string str)
{
std::cout << str << std::endl;
}
int main()
{
std::map<std::string, int> map; …Run Code Online (Sandbox Code Playgroud) 根据这个答案,iterator必须可以隐含地转换为const_iterator.insert_or_assign()既然如此,正如我们可以看到的那样,为什么在C++ 17中添加了新的签名std::map::erase()?
在C++ 11中,我们有 iterator erase( const_iterator pos );
在C++ 17中,我们现在有了 iterator erase( iterator pos );
是不是C++ 11签名足以接收iterator和const_iterator?
例如,'a'具有ASCII码97,我们可以使用
char ch = 'a';
Run Code Online (Sandbox Code Playgroud)
要么
char ch = 97;
Run Code Online (Sandbox Code Playgroud)
用auto我们可以写
auto ch = 'a';
Run Code Online (Sandbox Code Playgroud)
对于第一种情况,但如何在演绎期间通过数字ascii代码获取char变量?
这对我不起作用:
auto ch = '\97';
Run Code Online (Sandbox Code Playgroud) (据我所知,使用的编译器是带有 c++17 的 gcc(在 Visual Studio 中很难找到))
#include <iostream>
using namespace std;
void increment( int& v )
{
++v;
}
int constexpr f()
{
int v = 0;
increment( v );
return v;
}
int main( )
{
cout << f( ) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
上面的代码给出了编译错误:
constexpr 函数 'f' 不能产生常量表达式。
据我了解,这是因为该函数increment不是 constexpr。让我困惑的是以下代码编译得很好:
#include <iostream>
using namespace std;
void increment( int& v )
{
++v;
}
int constexpr f()
{
int v = 0;
for( int i = 0; …Run Code Online (Sandbox Code Playgroud) 假设我有:
template<int... N>
class seq
{
};
template<int... N>
struct uniq{
using type = seq<N...>;
};
Run Code Online (Sandbox Code Playgroud)
我需要以某种方式使序列唯一,以便
std::is_same_v<uniq<1,2,2,2,3,3,3>::type, seq<1, 2, 3>>;
Run Code Online (Sandbox Code Playgroud)
最终是真的。换句话说,使序列唯一,然后创建一个 seq。
有没有办法在编译时实现这一点?