C#0x中的C#样式Action <t>,Func <t,t>等</t,t> </t>

时间:2010-04-22 03:50:17

标签: c# c++ templates lambda c++11

C#具有通用功能类型,例如Action<T>Func<T,U,V,...>

随着C ++ 0x的出现以及具有模板typedef和可变参数模板参数的能力,似乎这应该是可能的。

对我来说显而易见的解决方案是:

template <typename T>
using Action<T> = void (*)(T);

但是,这不适用于仿函数或C ++ 0x lambdas,除此之外,不会编译错误“expected unqualified-id before 'using'

我的下一次尝试是使用boost :: function:

template <typename T>
using Action<T> = boost::function<void (T)>;

由于同样的原因,这也无法编译。

我唯一的另一个想法是STL样式模板参数:

template <typename T, typename Action>
void foo(T value, Action f) {
    f(value);
}

但是这不提供强类型解决方案,只与模板化函数有关。

现在,我将第一个承认我不是C ++,我更愿意认为我是,所以很可能有一个我没有看到的明显解决方案。

C ++中是否可以使用C#样式泛型函数类型?

3 个答案:

答案 0 :(得分:6)

我认为语法应该是这样的:

template <typename T>
using Action = void (*)(T);

虽然(g ++ v4.3.2),但我无法编译。

一般的STL样式函数模板在严格意义上不是强类型的,但它是类型安全的,因为编译器将确保模板仅针对满足函数的所有要求的类型进行实例化。具体而言,如果Action无法使用T类型的一个参数进行调用,则会出现编译器错误。这是一种非常灵活的方法,因为将Action实例化为函数或某个实现operator()的类并不重要。

缺少模板化typedef的旧的非C ++ 0x解决方法是使用带有嵌套typedef的模板化结构:

template <typename T>
struct Action {
   typedef boost::function<void (T)> type;
};

template <typename T>
void foo(T value, typename Action<T>::type f) {
    f(value);
}

答案 1 :(得分:1)

Gcc不支持模板别名(请参阅here),我不确定是否考虑了可变参数模板别名。我认为其他编译器不支持此功能。

我将使用std :: function或std :: function而不是Action或Func。

当然你可以从std :: function定义可变参数模板类Action或Func,但我没有看到它的好处。

答案 2 :(得分:1)

我认为通用函数类型不是直观的C ++,因为C ++模板与泛型不同。

C ++的方法是使用函数对象 - 您可以将()放在后面的任何东西,它对编译器有意义。这可以是函数指针,具有operator()的类,依此类推。这是有效的,因为C ++模板就像花哨的宏一样,只要代码对替换类型有意义,你就可以了。

C#泛型不能那样工作 - 它们更具限制性,可能是为了改进错误消息(因为输出C ++模板错误在输出中很常见)。我不太了解C#泛型,但我认为它们依赖于更像回调的东西,因此函数泛型的用处。