在lambda中使用类模板参数时的编译错误

时间:2011-07-06 15:19:24

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

我正在尝试在C ++中重新创建C#的委托类型的一些行为,并且我在编译时遇到了一个特定的错误 - 这里是相关的代码:

struct Nil { };

// Represents a C# Func
template <typename returnType = void,
          typename T1 = Nil,
          typename T2 = Nil,
          typename T3 = Nil>
class Func
{
public:
    vector<function<returnType(T1, T2, T3)>> _funcs;

    void operator+=(returnType (*functionPointerToAdd)(T1))
    {
        auto myFunc = [&] ( returnType (*functionPointerToAdd)(T1) )
                     -> returnType (*)(T1, T2, T3)
                     { functionPointerToAdd(T1); };
        // add myFunc to the vector of functions...
    }
};

我要做的是将一个函数指针包装在一个闭包中,该闭包的签名与该类的完整模板类型匹配(有效地“丢弃”设置为'Nil'的值)。我得到的错误是:

error C2275: 'T1' : illegal use of this type as an expression

我正在使用MSVC10,我尝试按照Accessing a class template parameter type inside a member function with a lambda fails键入模板变量,但无济于事。我意识到这个特定的实现存在一些问题,我会遇到这个问题,但除此之外,我只是好奇为什么我不能在lambda语句中使用类的模板参数。 / p>

2 个答案:

答案 0 :(得分:7)

我认为你的0x语法仍然有些混乱。

auto myFunc = [&] ( returnType (*functionPointerToAdd)(T1) ) -> returnType (*)(T1, T2, T3) { functionPointerToAdd(T1); };

这一行是问题所在。让我们分开吧:

auto myFunc = [&]

这会创建一个未定义类型的局部变量,它接收一个lambda(很好)并启动一个lambda,它通过引用获取函数指针。指针将会消失,为了简单起见,最好使它成为[=](你将更多地复制一个完整的指针 - 没有大问题。)

( returnType (*functionPointerToAdd)(T1) ) 

这是lambda的参数。这意味着应该使用returnType(*)(T1)类型的函数指针调用lambda(!)。这不是你想要的 - 你希望用T1,T2,T3来调用它。

-> returnType (*)(T1, T2, T3)

这定义了lambda的返回类型 - 只有那个。你现在要说它必须返回一个函数指针,返回一个函数返回一个returnType并将T1,T2和T3作为参数。那么lambda类型将是

(returnType(*)(T1, T2, T3)) (*)(returnType(*)(T1))

,或将函数指针作为参数并返回函数指针的函数。是的,它过于复杂且难以理解。

{ functionPointerToAdd(T1); };

这最终是lambda的内容和错误的原因。您将类型T1作为参数传递给函数指针。

修复它的建议(因为语法非常复杂 - 我希望上面的文字可以帮助你改变原因:

auto myFunc = [=] ( T1 arg, T2, T3 ) -> returnType { return functionPointerToAdd(arg); }

随意问为什么&amp;如何。

答案 1 :(得分:0)

我认为错误正是编译器所说的:你的电话functionPointerToAdd(T1)没有意义。 T1是一种类型,而不是变量。你的lambda只接受一个函数指针作为参数,但没有实际的对象来调用函数!

此外,什么是lambda应该返回?如果它的唯一目的是返回functionPointerToAdd(...),那么它的返回类型不应该只是returnType吗?

也许这样的事情(但我完全不了解你的要求):

typedef returnType (*myFP)(T1);

auto myFunc = [] (myFP f, const T1 & t) -> returnType { return f(t); };

我也摆脱了“通过引用捕获所有东西”([&]),因为你似乎没有使用任何非局部变量。

编辑哦,等等,我知道,您想将myFunc添加到向量中。因此,您希望将给定指针绑定到一个lambda,该lambda的主体包括调用该函数。好的,让我们看看:

void operator+=(myFP f)
{
  auto myFunc = [f] (T1 t, T2, T3) -> returnType { return f(t); };
  the_vector.push_back(myFunc);
}

但我怀疑你能做到这一点,因为从环境中捕获的lambda不能转换为裸函数指针,我相信。我们确实需要一个合适的函数对象来解决你的问题。