- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想要一个通用的 zipWith 函数在 C++ 变量arity。我有两个问题。首先是我无法确定传递给 zipWith 的函数指针的类型。它必须与传递给 zipWith 的 vector 数量相同,并且必须分别接受对 vector 元素类型的引用。第二个是我不知道如何并行遍历这些 vector 来构建参数列表、调用 func() 并在最短的 vector 用完后保释。
template <typename R, typename T, typename... Vargs>
std::vector<R> zipWith (R func(???<what goes here>), std::vector<T> first, Vargs rest) {
???
}
最佳答案
我有一个很长的答案,然后我改变了主意,使解决方案变得更短。但我将展示我的思考过程并给你们两个答案!
我的第一步是确定正确的签名。我不了解所有内容,但您可以将参数包视为隐藏文本转储的实际项目的逗号分隔列表。您可以通过更多以逗号分隔的项目扩展任一侧的列表!所以直接应用:
template <typename R, typename T, typename... Vargs>
std::vector<R> zipWith (R func(T,Vargs...), std::vector<T> first, Vargs rest) {
???
}
template <typename R, typename T, typename... Vargs>
std::vector<R> zipWith (R func(T,Vargs...), std::vector<T> first, Vargs... rest) {
???
}
Vargs
真的是
std::vector
.类型转换可以应用于参数包,那么我们为什么不确保您拥有 vector :
template <typename R, typename T, typename... Vargs>
std::vector<R> zipWith (R func(T,Vargs...), std::vector<T> first, std::vector<Vargs> ...rest) {
???
}
const
l 值引用。此外,我们可以使用
std::function
所以我们可以使用 lambda 或
std::bind
表达式:
template <typename R, typename T, typename... Vargs>
std::vector<R> zipWith (std::function<R(T, Vargs...)> func, std::vector<T> const &first, std::vector<Vargs> const &...rest) {
???
}
std::pow
进行测试时遇到了问题。我的编译器不接受将经典函数指针转换为
std::function
对象。所以我不得不将它包装在 lambda 中。也许我应该在这里问一下....)
template < typename R, typename T, typename ...MoreTs >
std::vector<R>
zip_with( std::function<R(T,MoreTs...)> func,
const std::vector<T>& first, const std::vector<MoreTs>& ...rest )
{
auto const tuples = rearrange_vectors( first, rest... );
std::vector<R> result;
result.reserve( tuples.size() );
for ( auto const &x : tuples )
result.push_back( evaluate(x, func) );
return result;
}
func
的评估结果每一次。
rearrange_vectors
必须提前制作值表(默认构造)并一次填写每个条目一个子对象:
template < typename T, typename ...MoreTs >
std::vector<std::tuple<T, MoreTs...>>
rearrange_vectors( const std::vector<T>& first,
const std::vector<MoreTs>& ...rest )
{
decltype(rearrange_vectors(first, rest...))
result( first.size() );
fill_vector_perpendicularly<0>( result, first, rest... );
return result;
}
std::forward
括起来。 (或
move
)因此不会错误地选择递归调用的左值重载。改变每个元组元素的一部分的函数必须显式地采用当前索引。参数包剥离期间索引向上移动1:
template < std::size_t, typename ...U >
void fill_vector_perpendicularly( std::vector<std::tuple<U...>>& )
{ }
template < std::size_t I, class Seq, class ...MoreSeqs, typename ...U >
void fill_vector_perpendicularly( std::vector<std::tuple<U...>>&
table, const Seq& first, const MoreSeqs& ...rest )
{
auto t = table.begin();
auto const te = table.end();
for ( auto f = first.begin(), fe = first.end(); (te != t) && (fe
!= f) ; ++t, ++f )
std::get<I>( *t ) = *f;
table.erase( t, te );
fill_vector_perpendicularly<I + 1u>( table, rest... );
}
fe
块中将
const
标记为
for
。)我最初有
first
和
rest
如
std::vector
,但我意识到我可以把它抽象出来;我所需要的只是与迭代界面中的标准(序列)容器相匹配的类型。但现在我难住了
evaluate
:
template < typename R, typename T, typename ...MoreTs >
R evaluate( const std::tuple<T, MoreTs...>& x,
std::function<R(T,MoreTs...)> func )
{
//???
}
template < typename R >
R evaluate( const std::tuple<>& x, std::function<R()> func )
{ return func(); }
template < typename R, typename T >
R evaluate( const std::tuple<T>& x, std::function<R(T)> func )
{ return func( std::get<0>(x) ); }
std::tuple
不支持将尾部(和/或头部)剥离为子元组。
std::bind
也没有支持零散地将参数柯里化到函数中,并且其占位符系统与任意长度的参数包不兼容。我希望我可以像我可以访问原始输入 vector 一样列出每个参数......
zipWith
中展示了它.我可以从函数参数列表到函数内部吗? (在我写的时候,我现在记得在类构造函数的成员初始化部分看到它,对于数组或类类型的非静态成员。)只有一种方法可以找到:
template < typename R, typename T, typename ...MoreTs >
std::vector<R>
zip_with( std::function<R(T,MoreTs...)> func, const std::vector<T>&
first, const std::vector<MoreTs>& ...rest )
{
auto const s = minimum_common_size( first, rest... );
decltype(zip_with(func,first,rest...)) result;
result.reserve( s );
for ( std::size_t i = 0 ; i < s ; ++i )
result.push_back( func(first[i], rest[i]...) );
return result;
}
inline std::size_t minimum_common_size() { return 0u; }
template < class SizedSequence >
std::size_t minimum_common_size( const SizedSequence& first )
{ return first.size(); }
template < class Seq, class ...MoreSeqs >
std::size_t
minimum_common_size( const Seq& first, const MoreSeqs& ...rest )
{ return std::min( first.size(), minimum_common_size(rest...) ); }
std::vector
的替换具有通用序列容器类型的可以应用于
zip_width
.我意识到我可以将强制的单 vector 减少到无强制 vector :
template < typename R, typename ...T, class ...SizedSequences >
std::vector<R>
zip_with( R func(T...) /*std::function<R(T...)> func*/,
SizedSequences const& ...containers )
{
static_assert( sizeof...(T) == sizeof...(SizedSequences),
"The input and processing lengths don't match." );
auto const s = minimum_common_size( containers... );
decltype( zip_with(func, containers...) ) result;
result.reserve( s );
for ( std::size_t i = 0 ; i < s ; ++i )
result.push_back( func(containers[i]...) );
return result;
}
static_assert
因为我在这里复制了代码,因为我忘记确保
func
的参数计数和输入 vector 的数量一致。现在我意识到我可以修复决斗函数指针 vs.
std::function
通过抽象两个对象:
template < typename R, typename Func, class ...SizedSequences >
std::vector<R>
zip_with( Func&& func, SizedSequences&& ...containers )
{
auto const s = minimum_common_size( containers... );
decltype( zip_with<R>(std::forward<Func>(func),
std::forward<SizedSequences>(containers)...) ) result;
result.reserve( s );
for ( std::size_t i = 0 ; i < s ; ++i )
result.push_back( func(containers[i]...) );
return result;
}
const
/
volatile
(简历)资格。这就是为什么我换了
containers
到它。
func
可以有任何结构;它甚至可以是具有多个版本
operator ()
的类对象.由于我对容器使用 r 值,因此它们将使用最佳的 cv 限定来取消引用元素,并且该函数可以将其用于重载解析。内部确定结果类型的递归“调用”需要使用
std::forward
防止对左值引用的任何“降级”。它还揭示了本次迭代中的一个缺陷:I
必须提供返回类型。
#include <algorithm>
#include <cstddef>
#include <iterator>
#include <utility>
#include <vector>
inline std::size_t minimum_common_size() { return 0u; }
template < class SizedSequence >
std::size_t minimum_common_size( const SizedSequence& first )
{ return first.size(); }
template < class Seq, class ...MoreSeqs >
std::size_t minimum_common_size( const Seq& first,
const MoreSeqs& ...rest )
{
return std::min<std::size_t>( first.size(),
minimum_common_size(rest...) );
}
template < typename OutIter, typename Func, class ...SizedSequences >
OutIter
zip_with( OutIter o, Func&& func, SizedSequences&& ...containers )
{
auto const s = minimum_common_size( containers... );
for ( std::size_t i = 0 ; i < s ; ++i )
*o++ = func( containers[i]... );
return o;
}
template < typename Func, class ...SizedSequences >
auto zipWith( Func&& func, SizedSequences&& ...containers )
-> std::vector<decltype( func(containers.front()...) )>
{
using std::forward;
decltype( zipWith(forward<Func>( func ), forward<SizedSequences>(
containers )...) ) result;
#if 1
// `std::vector` is the only standard container with the `reserve`
// member function. Using it saves time when doing multiple small
// inserts, since you'll do reallocation at most (hopefully) once.
// The cost is that `s` is already computed within `zip_with`, but
// we can't get at it. (Remember that most container types
// wouldn't need it.) Change the preprocessor flag to change the
// trade-off.
result.reserve( minimum_common_size(containers...) );
#endif
zip_with( std::back_inserter(result), forward<Func>(func),
forward<SizedSequences>(containers)... );
return result;
}
minimum_common_size
在这里,但明确提到了最小基本情况的结果类型,使用不同大小类型针对不同容器类型进行校对。
zip_width
必须使用后者,因为参数包必须放在最后。
zipWith
中的后缀返回类型在计算返回类型表达式时,使函数签名的每个部分都公平游戏。如果由于编译时不兼容而无法完成计算,它也会让我立即知道。
std::back_inserter
函数返回一个特殊的输出迭代器到通过
push_back
添加元素的 vector 。成员函数。
关于c++ - 是否可以在 C++ 中编写通用的可变参数 zipWith?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9729127/
我正在实现一个函数 combine::[[a]] -> [[b]] -> (a -> b -> c) -> [[c]] 它给出两个 2D 列表,将给定函数 f::a -> b -> c 应用于 2D
我想总结一个压缩列表。 averageGrade :: [Float] -> [Int] -> Float averageGrade [0.75 , 0.25] [6, 4] , result: 0,
我正在尝试实现经典的高阶范围 zipWith如下 import std.traits: allSatisfy; import std.range: isInputRange; auto zipWith
我正在尝试编写一个具有类型安全长度的向量库,这意味着添加两个不同长度的向量将不会成功。 我目前的实现大致是: data Natural where Zero :: Natural Succ :
Haskell 的 zipWith 的类似物是什么? Python 中的函数? zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 最佳答案 map() map
初步说明:这是 a deleted question by SeanD 的转版. 就像有 zipWith对于列表... GHCi> zipWith (+) [1,2] [3,4] [4,6] ...感
我的空间泄漏发生在我的一个个人项目中。但我不希望有人在我的项目中解决它。我想了解它。 我通过制作这个算法重现了我的空间泄漏: u 是由以下定义的序列: u(0) = 1 u(1) = 2 u(2) =
在代码审查中,我回答了一个关于 naive Haskell fizzbuzz solution 的问题。通过建议 iterates forward 的实现,避免了增加素数的二次成本和(几乎)完全丢弃模
我已经到了这一步: implicit def collectionExtras[A](xs: Iterable[A]) = new { def zipWith[B, C, That](ys: It
我一直在尝试在不使用惰性 zipwith 的情况下实现从 0 到 n 的斐波那契数列列表方法。到目前为止,我所拥有的是从 n 返回列表的代码。到 1. 有什么办法可以更改此代码,使其从 0- n 返回
我已经使用递归重写了 zipWith 函数,现在我尝试使用列表理解重写它。我遇到了很多绑定(bind)错误,并且我知道我的第二行不正确。这是我的函数,它的工作原理类似于使用递归的 zipWith: z
我必须创建一个名为 differences 的函数,在其中我使用 zipWith 计算每对的差异并将其放入列表中。 例如 差异 [1..5] == [1, 1, 1, 1]。 所以 [2-1, 3-2
我必须创建一个名为 differences 的函数,在其中我使用 zipWith 计算每对的差异并将其放入列表中。 例如 差异 [1..5] == [1, 1, 1, 1]。 所以 [2-1, 3-2
我有两个大小相等的数组,我想按元素组合它们。做这个的最好方式是什么? array 包似乎没有提供 zipWith 等效函数。 我不太愿意做自己的函数,因为我能想到的主要方法是用列表来回转换。我关心速度
处理业务的时候一定有这样的需求:将多个源数据压缩成一个,Reactor提供了zip和zipWith方法可以做到这一点。 zip和zipwith有些不同: zip可以一次合并多个源 zipWiht一次只
我想要一个通用的 zipWith 函数在 C++ 变量arity。我有两个问题。首先是我无法确定传递给 zipWith 的函数指针的类型。它必须与传递给 zipWith 的 vector 数量相同,并
我一直在尝试理解这段代码,但我无法清楚地概括它: ghci > :t zipWith zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] ghci > :t (
我正在尝试在 Haskell 中编写 Zipwith 函数。 如果我使用以下值运行它,它应该返回以下结果: Prelude> zipWith (+) [10,20,30] [33,44,94] [43
ghci> zipWith' (zipWith' (*)) [[1,2,3],[3,5,6],[2,3,4]] [[3,2,2],[3,4,5],[5,4,3]] 函数 zipWith' 使用函数 '
我正在使用 Haskell 表达学院学习 Haskell:通过多媒体学习函数式编程,我不确定如何解决这个练习。 Using the definition of trees given by data
我是一名优秀的程序员,十分优秀!