我正在开发一个使用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?
通用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是引擎盖下的模板化功能对象,这是不是有点奇怪,这是不能做到的?
可以说我有一个字符串向量,我想找到所有以开头的字符串'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_bound,std::upper_bound并且std::equal_range何时可以轻松地将其由lambda捕获或传递给比较结构,然后才根本不存在此问题?
如果std::equal_range不要求价值怎么办?
struct cmp {
cmp( char lc ) : c( lc …Run Code Online (Sandbox Code Playgroud) 我写了一些代码,在给定通用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) 我想编写一个具有泛型方法的函数式非泛型接口的实现。实现需要是内联闭包并且简洁。
作为一个简化的例子
@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 …
假设您有一个带有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()上面函数的第二个版本?
我尝试使用通用递归函数遍历树状结构,而不是每次为每个结构定义全局的递归函数.
//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) 我目前正在尝试使用类模板编程,并且遇到了这种奇怪的行为,在将命名的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) 我想模仿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
我正在尝试编写一个函数,该函数将返回带有可变参数的泛型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不是通用的 - 它不适用于任何任意参数包.