c ++ 14引入了通用lambdas,可以编写以下内容:
auto func = [](auto a, auto b){
return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");
Run Code Online (Sandbox Code Playgroud)
很明显,这个通用lambda func就像模板化函数func一样有效.
为什么C++委员会决定为通用lamda添加模板语法?
在Boost邮件列表中,@ LouisDionne最近发布了以下创建类似元组的实体的巧妙技巧:
#include <iostream>
auto list = [](auto ...xs) {
return [=](auto access) { return access(xs...); };
};
auto length = [](auto xs) {
return xs([](auto ...z) { return sizeof...(z); });
};
int main()
{
std::cout << length(list(1, '2', "3")); // 3
}
Run Code Online (Sandbox Code Playgroud)
实例.
聪明之处在于listlambda采用可变参数列表作为输入,并返回lambda作为输出,将另一个lambda作用于其输入.类似地,lengthlambda是一个类似列表的实体,它将sizeof...向列表的原始输入参数提供可变参数运算符.在sizeof...操作上缠绕有拉姆达的内部,使得它可以被传递给list.
问题:这个元组创作成语是否有名称?也许来自函数式编程语言,其中更常用的是高阶函数.
std::visit()在cppreference中查看页面时,https: //en.cppreference.com/w/cpp/utility/variant/visit,
我遇到了我无法理解的代码......
这是缩写版本:
#include <iomanip>
#include <iostream>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;
int main() {
std::vector<std::variant<int,long,double,std::string>> vec = { 10, 15l, 1.5, "hello" };
for (auto& v : vec) {
std::visit(overloaded{
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << …Run Code Online (Sandbox Code Playgroud) 据我所知 - 泛型lambda被转换为具有模板化的局部范围结构的对象operator().这使得通用lambda非常强大且易于使用的工具.另一方面,可以创建嵌套到函数中的结构,但是当结构具有模板化成员时,例如:
#include <iostream>
int main() {
struct inner {
template <class T>
void operator()(T &&i) { }
};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
或者自己模仿:
int main() {
template <class T>
struct inner {
void operator()(T &&i) { }
};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器似乎有编译它的问题:
Run Code Online (Sandbox Code Playgroud)error: invalid declaration of member template in local class和
Run Code Online (Sandbox Code Playgroud)error: a template declaration cannot appear at block scope
我认为问题在c ++标准中比在编译器bug中更多.lambdas被允许拥有模板化成员而不是本地结构的原因是什么?
我发现了这个问题,但我认为答案有点过时(即使对于c ++ 11,我也不认为这是真的).
我在C++中编写了一个匿名的阶乘函数,并用g ++ 4.9.2编译了我的代码.它运作良好.但是,我不知道我的功能类型.
#include<iostream>
#include<functional>
using std::function;
int main()
{
//tested at g++ 4.9.2
//g++ -std=c++1y -o anony anony.cpp
auto fac = [](auto self,auto n)->auto{
if(n < 1)
return 1;
else
return n * self(self,n-1);
};
std::cout<<fac(fac,3)<<std::endl;//6
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以,我想知道:什么类型fac和self?如果我只是将C++代码翻译成Haskell,它将无法编译,因为它涉及无限类型:
fac2 self 0 = 1
fac2 self n = n * (self self $ n-1)
Run Code Online (Sandbox Code Playgroud)
我必须定义一些递归类型的工作:
data Y a = Y ((Y a)->a->a)
fac2 self 0 = 1
fac2 self n = n * ((applY …Run Code Online (Sandbox Code Playgroud) 我正在尝试实现一个包含任意类型和互斥锁的类.要访问包装数据,需要传递一个仿函数作为locked方法的参数.然后包装类将包装的数据作为参数传递给仿函数.
我希望我的包装类使用const和非const,所以我尝试了以下内容
#include <mutex>
#include <string>
template<typename T, typename Mutex = std::mutex>
class Mutexed
{
private:
T m_data;
mutable Mutex m_mutex;
public:
using type = T;
using mutex_type = Mutex;
public:
explicit Mutexed() = default;
template<typename... Args>
explicit Mutexed(Args&&... args)
: m_data{std::forward<Args>(args)...}
{}
template<typename F>
auto locked(F&& f) -> decltype(std::forward<F>(f)(m_data)) {
std::lock_guard<Mutex> lock(m_mutex);
return std::forward<F>(f)(m_data);
}
template<typename F>
auto locked(F&& f) const -> decltype(std::forward<F>(f)(m_data)) {
std::lock_guard<Mutex> lock(m_mutex);
return std::forward<F>(f)(m_data);
}
};
int main()
{
Mutexed<std::string> str{"Foo"};
str.locked([](auto &s) …Run Code Online (Sandbox Code Playgroud) 这有两件事可行.我们可以实例化一个转发函数模板来获取一个带左值的函数指针:
template <class T>
void f(T &&) {}
void(*p)(int &) = f; // Cool!
Run Code Online (Sandbox Code Playgroud)
我们还可以将带有左值的非捕获通用lambda转换为带左值的函数指针:
auto l = [](auto &) { };
void (*lp)(int &) = l; // Still cool!
Run Code Online (Sandbox Code Playgroud)
但显然GCC和Clang都没有将转发通用lambda转换为带左值的函数指针:
auto l = [](auto &&) { };
void (*lp)(int &) = l; // Not cool!
Run Code Online (Sandbox Code Playgroud)
GCC产出:
<source>:9:21: error: invalid user-defined conversion from '<lambda(auto:1&&)>' to 'void (*)(int&)' [-fpermissive]
void (*lp)(int &) = l;
^
Run Code Online (Sandbox Code Playgroud)
Clang输出:
<source>:9:8: fatal error: no viable conversion from '(lambda at <source>:7:10)' to 'void (*)(int &)'
void …Run Code Online (Sandbox Code Playgroud) c++ templates function-pointers language-lawyer generic-lambda
我需要知道lambda具有的确切参数数量.我不关心他们的类型,我只需要一个计数.
auto lambda0 = [&]() { ... };
auto lambda1 = [&](int32_t a) { ... };
auto lambda2 = [&](int32_t a, auto b) { ... };
lambda_details<decltype(lambda0)>::argument_count; // Equals 0
lambda_details<decltype(lambda1)>::argument_count; // Equals 1
lambda_details<decltype(lambda2)>::argument_count; // Equals 2
Run Code Online (Sandbox Code Playgroud)
检测变量lambda也很好,所以我也可以处理那个边缘情况.
auto lambda_variadic = [&](auto... args){ ... };
lambda_details<decltype(lambda_variadic)>::is_variadic; // Equals true
Run Code Online (Sandbox Code Playgroud)
我怎样才能获得这些信息?
我有一个玩具示例,我想在架构上进行修改以删除Processoron的类型依赖性EmitterT:
#include <iostream>
#include <utility>
using namespace std;
struct Emitter {
void e(int) { cout << "emitting int\n";}
void e(double) { cout << "emitting double\n";}
void e(char*) { cout << "emitting char*\n";}
void e(const char*) { cout << "emitting const char*\n";}
};
template <typename EmitterT>
struct Processor {
Processor(EmitterT e) : e_{e} {}
template <typename T>
void process(T&& value) {
cout << "some processing... ";
e_(std::forward<T>(value));
}
EmitterT e_;
};
template<typename Emitter_>
Processor<Emitter_> makeProcessor(Emitter_ e) { …Run Code Online (Sandbox Code Playgroud) 我研究了泛型lambdas,稍微修改了这个例子,所以我的lambda应该捕获上层lambda的可变参数包.所以基本上给予上层lambda的是(auto&&...)- 应该以某种方式在[=]块中捕获.
(完美的转发是另一个问题,我很好奇这可能在这里吗?)
#include <iostream>
#include<type_traits>
#include<utility>
// base case
void doPrint(std::ostream& out) {}
template <typename T, typename... Args>
void doPrint(std::ostream& out, T && t, Args && ... args)
{
out << t << " "; // add comma here, see below
doPrint(out, std::forward<Args&&>(args)...);
}
int main()
{
// generic lambda, operator() is a template with one parameter
auto vglambda = [](auto printer) {
return [=](auto&&... ts) // generic lambda, ts is a parameter pack
{ …Run Code Online (Sandbox Code Playgroud)