【发布时间】:2011-02-03 11:24:00
【问题描述】:
我编写了一个特征类,可以让我提取有关 C++0x 中函数或函数对象的参数和类型的信息(使用 gcc 4.5.0 测试)。一般情况下处理函数对象:
template <typename F>
struct function_traits {
template <typename R, typename... A>
struct _internal { };
template <typename R, typename... A>
struct _internal<R (F::*)(A...)> {
// ...
};
typedef typename _internal<decltype(&F::operator())>::<<nested types go here>>;
};
然后我对全局范围内的普通函数进行了专门化:
template <typename R, typename... A>
struct function_traits<R (*)(A...)> {
// ...
};
这很好用,我可以将函数传递给模板或函数对象并且它可以正常工作:
template <typename F>
void foo(F f) {
typename function_traits<F>::whatever ...;
}
int f(int x) { ... }
foo(f);
如果我不想将函数或函数对象传递给foo,而是想传递一个 lambda 表达式,该怎么办?
foo([](int x) { ... });
这里的问题是function_traits<> 的特化都不适用。 C++0x 草案说表达式的类型是“唯一的、未命名的、非联合类类型”。对表达式调用 typeid(...).name() 的结果进行拆解,我得到了 gcc 对 lambda 的内部命名约定 main::{lambda(int)#1},而不是语法上代表 C++ 类型名的东西。
简而言之,有什么我可以在这里放入模板的吗:
template <typename R, typename... A>
struct function_traits<????> { ... }
这将允许该特征类接受 lambda 表达式?
【问题讨论】:
-
没有。为什么你认为你需要这样的东西?
-
我认为我的示例给出了一个不错的用例:如果我有一个接受函数或函数对象的通用算法,我可以使用这个特征类来确定返回类型(也可以现在用 decltype 完成),还有参数的类型。 (我省略了大部分代码以防止帖子过长。)因为我可以传入一个函数或函数对象,出于正交性的目的,我也希望能够传入一个 lambda。这基本上都是一个学术练习,源于阅读“编程元素”。
-
@Tony:答案是肯定的,我已经做到了。不过,我稍后会回到这个问题。你想获得什么特质?
-
我应该澄清一下:是的,这取决于你想要什么。
-
基本上我对函数结果的类型及其参数的类型/数量感兴趣;上面的模板中由 R 和 A... 表示的东西。我只是玩弄了一些其他形式的 lambda [](int x) { return x; } 可以显式地转换为常规函数指针 int(*)(int),所以似乎应该有一种方法可以利用它对我有利。我只需要将其与其他两个版本的 function_traits 一起工作,尤其是用于不专门处理其参数的函数对象的版本。
标签: c++ templates lambda c++11 specialization