C++ Lambda型演绎
基本上,我好奇的是,lambda中的变量是否有可能以任何方式推断返回值分配给的类型,在这种情况下,它是float和char。是否有与模板typename等效的名称?谢谢。我知道的唯一方法是使用模板参数:C++ Lambda型演绎,c++,lambda,return-value,type-deduction,C++,Lambda,Return Value,Type Deduction,基本上,我好奇的是,lambda中的变量是否有可能以任何方式推断返回值分配给的类型,在这种情况下,它是float和char。是否有与模板typename等效的名称?谢谢。我知道的唯一方法是使用模板参数: auto dothings = [](long position) { auto variable; /*do things*/ return variable; }; float x = dothings(1l); char y = dothings(2l); 模板 T点(长值) { T
auto dothings = [](long position) {
auto variable;
/*do things*/
return variable;
};
float x = dothings(1l);
char y = dothings(2l);
模板
T点(长值)
{
T结果;
...
返回结果;
}
自动x=dothings(1l);
自动y=点动(2l);
该模板还允许您专门化某些类型。因此,如果您想要不同的双精度逻辑,可以编写以下代码:
template<typename T>
T dothings(long value)
{
T result;
...
return result;
}
auto x = dothings<float>(1l);
auto y = dothings<char>(2l);
模板
双圆点(长值)
{
T结果;
...
返回结果*2.0;
}
这是可以做到的,但是a)有点复杂,b)不是一个好主意,99.9%的时间。下面是你如何进行的。根据将表达式指定给的类型执行操作的唯一方法是利用隐式转换。这需要一个模板化的隐式对话运算符,它不能在lambda中本地声明,因此我们必须先编写一些支持代码:
template<>
double dothings<double>(long value)
{
T result;
...
return result * 2.0;
}
这个lambda通过输入另一个lambda来创建我们特殊的ReturnConverter
类。这个lambda捕获外部lambda的长l
参数(按值),它准备接受我们的特殊标识类作为唯一参数。然后,它可以退出“目标”或目标类型。我在这里使用sizeof
快速显示一个示例,其中结果取决于lambda的参数和目标类型。但是请注意,一旦我使用decltype(t.get())
获得类型,我实际上可以声明该类型的变量,并对其执行我想要的任何操作
auto doIt = [] (long l) {
return makeReturnConverter([=] (auto t) {
return l + sizeof(decltype(t.get()));
});
};
在这些调用之后,x
将是9(浮点数的大小为4,+5),而y
将是10(双倍的大小为8,+2)
下面是一个更有趣的例子:
float x = doIt(5);
double y = doIt(2);
autodoit2=[](长l){
return makeReturnConverter([=](自动t){
decltype(t.get())x;
对于(std::size\u t i=0;i!=l;++i){
x、 推回(i*i);
}
返回x;
});
};
std::向量x=doIt2(5);
std::deque y=doIt2(5);
在这里,只要标准容器具有push\u-back
方法,我就能够根据左侧的要求一般地构建一个标准容器
正如我在开始时所说,在绝大多数情况下,这过于复杂,难以证明其合理性。通常,您可以将特定类型作为显式(非推断)模板参数,并在左侧显示auto
。不过,我已经在非常具体的案例中使用了它。例如,在gtest中,当您声明测试装置时,任何重用的数据都被声明为装置中的成员变量。非静态成员变量必须用它们的类型声明(不能使用auto),所以我使用这个技巧允许快速构建某些类型的fixture数据,同时尽可能地将重复保持在接近零的位置。在这个用例中是可以的,因为该代码不需要非常健壮,但确实希望以几乎任何代价最小化重复;通常这并不是一个很好的折衷办法(而且通常不需要在左侧提供auto
。这里的答案是否定的
返回的类型基于函数内部使用的值
auto doIt2 = [] (long l) {
return makeReturnConverter([=] (auto t) {
decltype(t.get()) x;
for (std::size_t i = 0; i != l; ++i ) {
x.push_back(i*i);
}
return x;
});
};
std::vector<int> x = doIt2(5);
std::deque<int> y = doIt2(5);
赋值运算符查看结果表达式的类型,以查看是否存在可用于将函数结果类型转换为赋值类型目标的自动转换
auto dothings = [](long position) {
auto variable; // This is illegal as the compiler can not deduce the type.
// An auto declaration needs some way for it to determine the type.
// So that when you use it below it can determine the
// return type of the function.
/*do things*/
return variable;
};
您可以将lambdas视为创建函子的语法糖
char x = dothings(10); // the result of the expression on the right
// is converted to char before assignment. If
// it can't be converted then it is a compiler error.
同:
[<capture List>](<Parameter List>) {
<Code>
}
struct
{
;
构造函数()
: ()
{}
运算符()()常量{
}
}{};
例如:
struct <CompilerGeneratedName>
{
<Capture List With Types>;
Constructor(<Capture List>)
: <Capture List With Types>(<Capture List>)
{}
<Calculated Return> operator()(<Parameter List>) const {
<Code>
}
}{<Capture List>};
{
int y=4;
自动l1=[&y](int x){返回y+++x;}
结构MyF
{
int&y;
MyF(国际和y)
:y(y)
{}
int运算符()(int x)常量{
返回y+++x;
}
};
自动l2=MyF(y);
std::它能为您编译吗?这不是重复的,他基本上是问泛型函数是否可以推断返回类型否,表达式的左侧不参与右侧的类型推断(模板转换运算符除外)。lambda不能使用右侧,因为右侧类型可以更改,即使lambda保持不变-但这需要它推断不同的类型。我在主要帖子“是否存在与模板typename等效的类型”中提到过它,专门询问lambda,但谢谢。这并没有回答问题。不回答问题的替代方案应该是注释。明确给出类型基本上与推导类型完全相反。我不知道为什么你没有得到爱。这是对所述问题的正确回答。可能:template struct标识{using type=T;};
和typename decltype(T)::type
而不是decltype(T.get())
@Jarod42我从那开始,最后似乎更长了。
struct <CompilerGeneratedName>
{
<Capture List With Types>;
Constructor(<Capture List>)
: <Capture List With Types>(<Capture List>)
{}
<Calculated Return> operator()(<Parameter List>) const {
<Code>
}
}{<Capture List>};
{
int y = 4;
auto l1 = [&y](int x){return y++ + x;}
struct MyF
{
int& y;
MyF(int& y)
: y(y)
{}
int operator()(int x) const {
return y++ + x;
}
};
auto l2 = MyF(y);
std::cout << l2(5) << " " << l1(5) << "\n";
}