小编Enr*_*lis的帖子

Range-v3 中是否有一种方法可以将元素添加到范围/视图中?

Range-v3 具有ranges::views::drop和 来ranges::views::drop_last从视图的前面或后面删除元素。

它是否提供类似的功能来将元素添加到视图中?

目前,我发现的最短方法是使用 a或 a到concat范围/容器:iotasingle

#include <assert.h>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/concat.hpp>
#include <range/v3/to_container.hpp>

using namespace ranges;
using namespace views;
int main() {
    std::vector<int> v{1,2,3};

    auto wi = concat(iota(0,1),v);
    assert(((wi | to_vector) == std::vector<int>{0,1,2,3}));

    auto ws = concat(single(0), v);
    assert(((ws | to_vector) == std::vector<int>{0,1,2,3}));
}
Run Code Online (Sandbox Code Playgroud)

c++ functional-programming range-v3 c++17 std-ranges

11
推荐指数
0
解决办法
637
查看次数

连接 string_view 对象

我一直std::string_view在一些旧代码中添加 s 来表示配置参数等字符串,因为它提供了只读视图,由于不需要复制,速度更快。

string_view但是,由于operator+未定义,因此无法将两个连接在一起。我看到这个问题有几个答案表明它是一个疏忽,并且有一个建议添加它。但是,这是添加 astring和 a string_view,大概如果实现的话,生成的串联将是std::string

添加两个string_view也属于同一类别吗?如果不是,为什么不string_view支持添加两个?

样本

std::string_view s1{"concate"};
std::string_view s2{"nate"};
std::string_view s3{s1 + s2};
Run Code Online (Sandbox Code Playgroud)

这是错误

error: no match for 'operator+' (operand types are 'std::string_view' {aka 'std::basic_string_view<char>'} and 'std::string_view' {aka 'std::basic_string_view<char>'})
Run Code Online (Sandbox Code Playgroud)

c++ string-concatenation string-view c++17

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

LYAH - 在链接 Writer monad 时理解关于“告诉”的评论

问题在底部以粗体显示。

LYAH 给出了这个使用monaddo符号的例子Writer

import Control.Monad.Writer

logNumber :: Int -> Writer [String] Int
logNumber x = writer (x, ["number " ++ show x])

multWithLog :: Writer [String] Int
multWithLog = do
              a <- logNumber 3
              b <- logNumber 5
              return (x*y)
Run Code Online (Sandbox Code Playgroud)

定义可以在没有do符号的情况下重写:

multWithLog = logNumber 3 >>= (\x ->
              logNumber 5 >>= (\y ->
              return (x*y)))
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好。

之后,书中介绍了tell,并编辑了这样的定义multWithLog

multWithLog = do
              a <- logNumber 3
              b <- logNumber 5
              tell ["something"]
              return …
Run Code Online (Sandbox Code Playgroud)

monads haskell rewriting do-notation writer-monad

8
推荐指数
1
解决办法
88
查看次数

模板专业化和参考

C++ 中的函数式编程中,第 11 章涉及一些基本的模板元编程。

在这种情况下,作者展示了remove_reference/ 的这种实现remove_reference_t,它与cppreference 中描述的那些实现基本相同。

template<typename T> struct remove_reference      { using type = T; };
template<typename T> struct remove_reference<T&>  { using type = T; };
template<typename T> struct remove_reference<T&&> { using type = T; };
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
Run Code Online (Sandbox Code Playgroud)

参考上面的代码,作者评论说,在“调用”时remove_reference_t<int>,只有general(或primary?这里的正确词是什么?)模板成功替代T,其他两个失败。这对我来说很清楚,没有办法int可以写成/匹配T&T&&

remove_reference_t<int&>然而,关于,作者说第二个专业无法匹配。好吧,由于引用折叠,它不能匹配吗?我的意思是,如果我替换为,则无法T&&匹配,从而得到?int&Tint&int&&& == int&

同样,在调用 时remove_reference_t<int&&>,不能将第一个专业化的T&匹配int&& …

c++ reference template-specialization template-meta-programming c++14

8
推荐指数
1
解决办法
177
查看次数

如果Either 可以是Left 或Right 但不能同时是两者,那么为什么它对应于Curry-Howard 对应中的OR 而不是XOR?

当我问这个问题,其中一个答案,现在删除,是在暗示该类型Either对应于XOR,而不是OR,在柯里-霍华德同构的,因为它不能LeftRight在同一时间。

真相在哪里?

haskell boolean-logic functional-programming category-theory curry-howard

8
推荐指数
3
解决办法
324
查看次数

为什么我不能到处使用 undefined ?

我以为我总是可以放在undefined我还不知道该放什么的同一个地方,并且代码应该可以很好地编译,只有在undefined实际评估时才会在运行时发生错误。

然而,就在这样做时,我开始写一些类似的东西

f = foldl undefined undefined undefined
Run Code Online (Sandbox Code Playgroud)

在文件中,当我尝试加载文件时,GHCi 出现此错误

source.hs:3:7: error:
    • Ambiguous type variable ‘t0’ arising from a use of ‘foldl’
      prevents the constraint ‘(Foldable t0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘t0’ should be.
      These potential instances exist:
        instance Foldable (Either a) -- Defined in ‘Data.Foldable’
        instance Foldable Maybe -- Defined in ‘Data.Foldable’
        instance Foldable ((,) a) -- Defined in ‘Data.Foldable’
        ...plus one other
        ...plus 29 instances …
Run Code Online (Sandbox Code Playgroud)

haskell functional-programming constraints typechecking

8
推荐指数
1
解决办法
117
查看次数

std::some-namespace::transform 有一天可以支持任何函子吗?

std::transform来自<algorithm>标题的内容适用于范围,它“使”我们能够使用范围作为它们本身的函子(在范畴论的意义上(\xc2\xb9))。std::transform是基于迭代器的,是的,但std::ranges::views::transform不是,并且它的签名与函数语言中相应函数的签名密切匹配(对两个参数的不同顺序取模,但这没什么大不了的)。

\n

当我看到这个问题(以及在回答它的过程中)时,我了解到 C++23 引入了std::optional<T>::transform,它std::optional也创建了一个函子。

\n

所有这些消息确实让我兴奋,但我不禁想到函子是通用的,如果有一个统一的接口就好了transform任何函子都有一个统一的接口会很好,例如 Haskell 中的情况。

\n

这让我认为类似的对象std::ranges::views::transform(具有不同的名称,而不是暗示ranges)可以成为一个定制点,STL不仅可以为范围定制,还可以为std::optionalSTL中的任何其他函子定制,而程序员可以为其用户定义的类定制它。

\n

非常相似,C++23 也引入了std::optional<T>::and_then,它基本上是 的一元绑定std::optional。我不知道有任何类似的函数可以实现范围的单子绑定,但 C++20本质上是withsome_range | std::ranges::views::transform(f) | std::ranges::views::join的单子绑定。some_rangef

\n

这让我认为可能存在一些通用接口,命名它mbind,人们可以选择使用任何类型。例如,STL 将选择std::optional通过按照 来实现它。std::optional<T>::and_then

\n

该语言是否有机会或有计划有一天支持这种通用性?

\n
\n

我当然可以看到一些问题。今天std::ranges::views::transform(some_optional, some_func)无效,因此某些代码可能依赖于 SFINAE。让它突然工作会破坏代码。 不完全是,破坏依赖于基于 SFINAE 的无效代码检测的代码是可以的。

\n
\n

(\xc2\xb9) 关于 …

c++ monads functional-programming functor c++23

8
推荐指数
1
解决办法
421
查看次数

为什么较新的 clang 比 popcntl 多生成一条指令来计算 haswell 架构上 int 的位数?

观看时Matt Godbolt 的演讲时时,我惊讶地发现,如果指示 Clang 针对 Haswell\xc2\xb9 架构进行编译,则会得出以下代码

\n
int foo(int a) {\n    int count = 0;\n    while (a) {\n        ++count;\n        a &= a - 1;\n    }\n    return count;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

用于计算设置位int(我不知道我自己需要多长时间才能计算出来),所以它只使用该指令:

\n
foo(int):                                # @foo(int)\n        popcntl %edi, %eax\n        retq\n
Run Code Online (Sandbox Code Playgroud)\n

我想自己尝试一下,但我发现生成的代码是

\n
foo(int):                                # @foo(int)\n        popcntl %edi, %eax\n        cmovel  %edi, %eax\n        retq\n
Run Code Online (Sandbox Code Playgroud)\n

事实证明,生成的代码在 Clang 10.0.1 和 Clang 11.0.0 之间发生了变化

\n

为什么较新的 Clang 又发出了一条以前不需要的指令?代码是如此简单,以至于我无法理解多一条指令除了使代码变慢之外还能做什么(即使速度可能非常小,我不知道)。

\n
\n

\xc2\xb9 作为一个附带问题,事实上不指定-march=haswell会导致更长、更人性化的代码这一事实是否仅仅意味着该选项所针对的物理 CPU 具有用于执行设置位计数和其他操作的电路(好吧,不管 clang 默认是什么)不?

\n

c++ assembly x86-64 clang bitcount

8
推荐指数
0
解决办法
140
查看次数

生成器在 C++20 视图管道中调用两次

在一个简单的views适配器管道中,调用一个gen函数来生成一系列值(使用内部状态),然后对其进行过滤。

令人惊讶和违反直觉的(至少对我来说)是这样的事实:生成器函数在每次迭代中被调用两次,因此对同一过滤器的下一次检查失败(过滤后的值不会在管道中重用)。

您知道这是否是正确的预期行为(以及为什么)?

libstdc++在 GCC 10.3、11.1 和 trunk(代码)以及range-v3GCC 和 clang(代码)中进行了测试。

int main() {
  int n = 0;
  auto gen = [&n]() {
    auto result = ++n;
    std::cout << "Generate [" << result << "]\n";
    return result;
  };

  auto tmp =
      ranges::views::iota(0)
      | ranges::views::transform([gen](auto &&) { return gen(); })
      | ranges::views::filter([](auto &&i) {
          std::cout << "#1 " << i << " " << (i % 2) << "\n";
          return (i …
Run Code Online (Sandbox Code Playgroud)

c++ range-v3 c++20 std-ranges

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

理解 C++ move_constructible 概念实现

move_constructible我从cppreference得到了以下 C++ 概念的实现

template<typename _Tp>
concept move_constructible =
    constructible_from<_Tp, _Tp> &&
    convertible_to<_Tp, _Tp>;
Run Code Online (Sandbox Code Playgroud)

我不明白为什么这有效。我认为任何类型都可以转换为自身,因此第二个要求是毫无意义的(上帝,我一定是在某些方面错了)。另外,对于第一个要求,我希望constructible_from<_Tp, _Tp&&>检查类型是否可以从 rvalue-ref 构造(因此移动)。

请解释一下这个实现是如何工作的。

c++ move-constructor move-semantics c++-concepts c++20

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