标签: generic-lambda

参数列表中带有省略号的C++ Lambda

我正在开发一个使用lambdas来描述表达式术语范围的库.因为库必须分发唯一的整数以标识每个变量,所以如果库(而不是用户)构造变量并且用户代码将它们作为lambda参数接收,则它是理想的.

(换句话说,我正在实现miniKanren的"call\fresh"的C++模拟.)

由于用户可能想要在特定范围内从零到多个新变量引入任何数字,我希望用户能够将具有不同数量参数的lambdas传递给库.但是,我不知道任何(简单的)方法(在C++ 14中)推导出任意lambda对象的参数数量.

我想到为什么不向lambda传递一个固定数量(比方说10)的variable-id参数,并让用户代码在lambda中使用省略号忽略不需要的那些?像这样的东西:

auto no_args = call_fresh([](...) { return success(); });
auto one_arg = call_fresh([](var A, ...) { return A == 1; });
auto two_args = call_fresh([](var A, var B, ...) { return A == 1 && B == 2; });
Run Code Online (Sandbox Code Playgroud)

编译器浏览器似乎接受lambda参数列表中的省略号,至少使用gcc.

它将被称为这样的东西(注意代码如何总是传递10个变量id,无论"f"是否只命名其中一个,两个或没有):

template <typename F>
auto call_fresh(F f)
{
   return [f](StateCounter sc) {
      return f(sc+0,sc+1,sc+2,sc+3,sc+4,
          sc+5,sc+6,sc+7,sc+8,sc+9);
   };
}
Run Code Online (Sandbox Code Playgroud)

虽然这是我感到惊讶的一个功能,有没有理由不使用带椭圆的lambdas?

c++ lambda variadic-functions generic-lambda c++14

6
推荐指数
2
解决办法
598
查看次数

将SFINAE与通用lambda一起使用

通用lambda可以利用"替换失败不是错误"规则吗?例

auto gL = 
    [](auto&& func, auto&& param1, auto&&... params) 
        -> enable_if_t< is_integral<
            std::decay_t<decltype(param1)>
        >::value>
    {
        // ...
    };

auto gL =  
     [](auto&& func, auto&& param1, auto&&... params) 
        -> enable_if_t< !is_integral<
            std::decay_t<decltype(param1)>
        >::value>
    {
        // ...
    };
Run Code Online (Sandbox Code Playgroud)

是否有任何变通方法或计划将其包含在语言中?此外,由于通用lambda是引擎盖下的模板化功能对象,这是不是有点奇怪,这是不能做到的?

c++ lambda sfinae generic-lambda c++14

5
推荐指数
1
解决办法
973
查看次数

std :: equal_range与lambda

可以说我有一个字符串向量,我想找到所有以开头的字符串'a',所以我可以这样做:

struct cmp {
    bool operator()( const std::string &s, char c ) const { return s.front() < c; }
    bool operator()( char c, const std::string &s ) const { return s.front() < c; }
};
std::vector<std::string> strings;
...
std::sort( strings.begin(), strings.end() );
auto range = std::equal_range( strings.begin(), strings.end(), 'a', cmp{} );
...
Run Code Online (Sandbox Code Playgroud)

此方法容易出错,因为很容易出错(例如,我认为应该c < s.front()在第二种方法中)并且具有代码重复功能。

那么可以使用通用lambda而不是2种方法来实现比较功能吗?

更笼统的问题是:为什么要比较的值必须作为参数传递给std::lower_boundstd::upper_bound并且std::equal_range何时可以轻松地将其由lambda捕获或传递给比较结构,然后才根本不存在此问题?

如果std::equal_range不要求价值怎么办?

struct cmp {
    cmp( char lc ) : c( lc …
Run Code Online (Sandbox Code Playgroud)

c++ lambda generic-lambda c++14

5
推荐指数
1
解决办法
1476
查看次数

从泛型lambda检测参数类型 - 使用GCC编译错误

我写了一些代码,在给定通用lambda函数时检索非auto参数的类型.正如您在下面的代码中看到的那样,我们的想法是使用通用lambda调用connect函数,并为auto参数提供参数(在我的用例中总是位于前面).所以在下面的代码中我的目标是检测第二个参数是float类型.

代码适用于clang 3.8,但它不能用gcc 6.1.1编译,所以我想知道这是否是gcc中的错误或者这是不是有效的c ++代码?我可以假设泛型lambda是使用模板化的operator()函数实现的,还是这个特定于编译器的?

template <typename Functor, typename... AllArgs, typename... ProvidedArgs>
void findArgTypes(void(Functor::*)(AllArgs...) const, Functor, ProvidedArgs...)
{
    // AllArgs == int, float
    // ProvidedArgs == int
}

template <typename Func, typename... ProvidedArgs>
void connect(Func func, ProvidedArgs... providedArgs)
{
    findArgTypes(&Func::template operator()<ProvidedArgs...>, func, providedArgs...);
}

int main()
{
    int tmp = 0;
    connect([&](auto, float){ ++tmp; }, 0);
}
Run Code Online (Sandbox Code Playgroud)

gcc给出的错误是这样的:

main.cpp: In instantiation of ‘void connect(Func, ProvidedArgs ...) [with Func = main()::<lambda(auto:1, float)>; ProvidedArgs = {int}]’:
main.cpp:16:33:   required from here
main.cpp:11:17: error: …
Run Code Online (Sandbox Code Playgroud)

c++ lambda gcc generic-lambda c++14

5
推荐指数
1
解决办法
399
查看次数

如何为泛型方法编写简洁的闭包?

我想编写一个具有泛型方法的函数式非泛型接口的实现。实现需要是内联闭包并且简洁。

作为一个简化的例子

@FunctionalInterface interface Fn {
    <R> R fn(R arg);
}
public class Scratch {
    Fn id = arg -> arg;
    //Fn nul = arg -> null;
    //Fn requiresNonNull = ...
}
Run Code Online (Sandbox Code Playgroud)

这使

/Scratch.java:5: error: incompatible types: invalid functional descriptor for lambda expression
    Fn id = arg -> arg;
            ^
    method <R>(R)R in interface Fn is generic
  where R is a type-variable:
    R extends Object declared in method <R>fn(R)
1 error
Run Code Online (Sandbox Code Playgroud)

(实际上,参数将是一个通用接口,其方法的返回类型为R。)

有没有一种解决方法,而无需回到匿名内部类的冗长?

有一个明显类似的问题,“无法将带有泛型方法的函数接口转换为 lambda …

java lambda generic-method generic-lambda

5
推荐指数
1
解决办法
310
查看次数

是否可以在lambda签名通用中创建模板变量?

假设您有一个带有std::vector任何类型的函数并以某种方式处理它:

template<typename T>
void foo(std::vector<T> &vec) {
    // work with vec
}
Run Code Online (Sandbox Code Playgroud)

因为C++14,我们能够用lambdas实现同样的目标.在这种情况下,我们将它们称为通用lambdas,因为我们为它们引入了类似模板的推导:

auto foo_lambda = [](std::vector<auto> &vec) {
    // work with vec
};
Run Code Online (Sandbox Code Playgroud)

但我们的选择似乎对我很有限.假设我不仅要引入类型推导,还需要引入模板值.例如,让我们std::vector改为std::array:

template<typename T, std::size_t size>
void foo(std::array<T, size> &arr) {
    // work with arr
}
Run Code Online (Sandbox Code Playgroud)

在处理模板函数时,我们可以引入一个模板值,可以用来匹配参数的需求.整齐.

我想用通用lambda实现相同的功能,但我无法这样做.

有没有办法将一个类似的推导值引入lambda表达式,这样任何std::arrays都可以与lambda一起使用,类似于foo()上面函数的第二个版本?

编辑:正如Evg的评论所述,我的vector<auto>语法是非标准的GCC扩展.有关详情请参阅此答案参照这个文件.

c++ lambda templates generic-lambda c++17

5
推荐指数
1
解决办法
190
查看次数

c ++,一种遍历树状结构的通用递归模板函数

我尝试使用通用递归函数遍历树状结构,而不是每次为每个结构定义全局的递归函数.

//structure #1
class CA
{
public:
    std::string name;
    std::vector<CA*> vecChild;
};
Run Code Online (Sandbox Code Playgroud)

我用CA创建了一个树

auto root = new CA;
root->name = "root";
root->push_back(new CA);
auto& childA = root->back();
childA->name = "childA";
root->push_back(new CA);
auto& childB = root->back();
childB->name = "childB";
...
Run Code Online (Sandbox Code Playgroud)

我可以使用此宏来遍历此结构,这可以与其他树状结构一起使用.

#define Combinator(obj, combinatorObjToContainer, containerNameOfObj, invokingGetCount, combinatorContainerToIndexingItem, TAnyObject, TAnyContainer, argEnterFunc, argLeaveFunc)\
{\
    std::function<void(TAnyObject, TAnyContainer)> RecursFunc = [&](auto& argObj, auto& argContainer)\
    {\
        argEnterFunc(argObj, argContainer);\
        for(size_t idx=0; idx<argObj combinatorObjToContainer containerNameOfObj invokingGetCount; ++idx)\
        {\
            RecursFunc(argObj, argObj combinatorObjToContainer containerNameOfObj combinatorContainerToIndexingItem [idx]);\
        }\
        argLeaveFunc(argObj, argContainer);\ …
Run Code Online (Sandbox Code Playgroud)

c++ macros templates generic-lambda c++14

5
推荐指数
1
解决办法
227
查看次数

将命名为lambda用作模板类参数或构造函数参数时,类模板无法编译

我目前正在尝试使用类模板编程,并且遇到了这种奇怪的行为,在将命名的lambda作为参数传递时我无法理解。有人可以解释为什么下面的(1)和(2)不起作用吗?

template<typename Predicate>
class Test{
public:
    Test(Predicate p) : _pred(p) {}
private:
    Predicate _pred;
};

int main(){
    auto isEven = [](const auto& x){ return x%2 == 0; };

    // Working cases
    Test([](const auto& x){ return x%2 == 0; });
    Test{isEven};
    auto testObject = Test(isEven);

    // Compilation Error cases
    Test(isEven); // (1) Why??? Most vexing parse? not assigned to a variable? I cant understand why this fails to compile.
    Test<decltype(isEven)>(isEven); // (2) Basically same as (1) but with a workaround. I'm …
Run Code Online (Sandbox Code Playgroud)

c++ lambda templates class-template generic-lambda

5
推荐指数
1
解决办法
71
查看次数

如何推导Lambda的返回类型?

我想模仿map()C ++中的Ruby 方法。我正在努力自动找出返回类型:

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>

typedef std::string T2;

template<class T1,
//  class T2, // gives "couldn't deduce template parameter 'T2'"
    class UnaryPredicate>
std::vector<T2> map(std::vector<T1> in, UnaryPredicate pred)
{
    std::vector<T2> res(in.size());
    std::transform(in.begin(), in.end(), res.begin(), pred);
    return res;
}

int main()
{
    std::vector<int> v1({1,2,3});
    auto v2(map(v1, [](auto el) { return "'"+std::to_string(el+1)+"'"; }));
    std::cout << v2[0] << "," << v2[1] << "," << v2[2] << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这样可以编译,但T2固定为string。如果使用其他T2定义,编译器会抱怨couldn't …

c++ lambda templates template-argument-deduction generic-lambda

5
推荐指数
1
解决办法
103
查看次数

如何从通用lambda中的variadic参数包中获取类型?

我正在尝试编写一个函数,该函数将返回带有可变参数的泛型lambda,其中lambda检查其中一个参数是否等于特定值.这是(大致)我正在尝试做的事情:

template <int Index, typename TValue>
inline auto arg_eq(const TValue& value) 
{
    return [value] (auto... args) -> bool {
        return (std::get<Index>(std::tuple</* ??? */>(args...)) == value);
    };
}
Run Code Online (Sandbox Code Playgroud)

我不确定在std::tuple</* ??? */>模板参数中放什么.我试过decltype(args),decltype(args...),auto,auto...,和其他一些东西,但我不断收到编译器错误.这甚至可能吗?

非通用的等价物将是这样的:

template <int Index, typename TValue, typename... TArgs>
inline auto arg_eq(const TValue& value)
{
    return [value] (TArgs... args) -> bool {
        return (std::get<Index>(std::tuple<TArgs...>(args...)) == value);
    };
}
Run Code Online (Sandbox Code Playgroud)

这工作正常,但返回的lambda不是通用的 - 它不适用于任何任意参数包.

c++ lambda variadic-templates generic-lambda c++14

4
推荐指数
2
解决办法
637
查看次数