【发布时间】:2011-12-12 05:35:24
【问题描述】:
我一直在使用新的 C++11 lambda,完全指定模板参数的要求是一个真正的拖累。我希望喜欢使用的语法类似于以下内容:
#include <vector>
#include <algorithm>
struct foo
{
void bar() {}
};
int main()
{
vector<foo> v(10);
for_each(v.begin(), v.end(), [](f) {f.bar();});
^^^
}
有什么办法可以得到接近这个的东西吗? Boost 的 Phoenix 库还可以,但是调用成员函数的语法需要 lots 样板——我想我是在 C++11 调用成员函数的简便性以及 Phoenix 的类型自动推导之后。
当前想法
我已经把它归结为这个语法:
vector<foo> x(1);
vector<bar> y(1);
for_each(x.begin(), x.end(), [](_a f) {f->f();});
for_each(y.begin(), y.end(), [](_a b) {b->b();});
这可行,但您必须为每种类型添加功能(例如ADD_AUTO_LAMBDA_SUPPORT(foo);)。它还有一个限制,即所有支持的类型都不能有任何模棱两可的成员。
完整的代码是:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
struct foo
{
foo() : x(3) {}
int x;
void f() { cout << x << endl;}
};
struct bar
{
bar() : y(133.7) {}
double y;
void b() { cout << y << endl;}
};
struct combo : foo, bar { };
struct _a
{
_a(foo& f) : offset(reinterpret_cast<combo*>(&f)) {}
_a(bar& b) : offset(reinterpret_cast<combo*>((char*)&b - 2*sizeof(foo))) {}
combo* operator->() { return offset; }
private:
combo* offset;
};
int main()
{
vector<foo> x(1);
vector<bar> y(1);
for_each(x.begin(), x.end(), [](_a f) {f->f();});
for_each(y.begin(), y.end(), [](_a b) {b->b();});
}
然后您可以使用一些模板和预处理器的魔法来生成_a 和combo,但是当您的名称不明确时就会出现问题(例如,带有b() 函数的第三个结构 - 您需要一种方法来消除我目前无法想到的歧义。
【问题讨论】:
-
我猜你可以使用
const decltype(v)::value_type& f,它对于很长的类型可能会更短。太糟糕了,我们使用auto作为参数类型。无论如何,您添加的所有这些废话都是 IMO 的粗俗和不良做法。 -
你是说你做这一切是为了剃掉一个角色?
for_each(x.begin(), x.end(), [](foo f) {f->f();});怎么了? -
(a) 因为它将算法与所使用的数据类型联系得更少,(b) 因为编译器 可以 计算出类型,因此应该,并且 (c ) 因为,当类型变得复杂时,它开始节省很多,并大大减少了行的混乱和样板:
for_each(x.begin(), x.end(), [&](const first_type& a, const second_type& b) { return a + b; }与for_each(x.begin(), x.end(), [](a, b) { return a + b; }节省了近 40 个字符! -
或者当你开始在地图上操作时,
for_each(m.begin(), m.end(), [&](const map<key_type, value_type>::value_type& x) {...}与for_each(m.begin(), m.end(), [&](x) {...} -
一点背景信息:Herb Sutter 说 C++ 委员会考虑添加“auto”作为参数类型专门为此。但是,他们得出结论,正常功能也必须支持这一点。而且因为他们担心如此巨大的变化,尤其是在 C++11 开发的后期,会延迟整个标准,所以他们完全忽略了它。
标签: c++ templates lambda c++11