开发者

Compilation error when using class template parameter in lambda

开发者 https://www.devze.com 2023-03-18 16:21 出处:网络
I\'m trying to recreate some of the behavior of C#\'s delegate types in C++, and I\'m running in to a particular error when compiling- here is the relevant code:

I'm trying to recreate some of the behavior of C#'s delegate types in C++, and I'm running in to a particular error when compiling- here is the relevant code:

struct Nil { };

// Represents a C# Func
template <typename returnType = void,
          typename T1 = Nil,
          typename T2 = Nil,
          typen开发者_StackOverflow社区ame 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...
    }
};

What I'm trying to do is wrap a function pointer in a closure whose signature matches the full template type of the class (effectively "throwing away" the values set to 'Nil'). The error I'm getting is:

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

I'm using MSVC10, and I tried typedef'ing the template variables as per Accessing a class template parameter type inside a member function with a lambda fails, to no avail. I realize there are a couple of issues with this particular implementation that I'll run into down the line but aside from that, I'm just curious as to why I can't use the class' template parameters in the lambda statement.


I think you still have the 0x syntax slightly messed up.

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

This line is the problem. Let's pull it apart:

auto myFunc = [&]

This creates a local variable of undefined type that receives a lambda (which is fine) and starts a lambda, that takes the function pointer by reference. The pointer is going to go away, better make it a [=] for simplicity (you'll copy a full pointer more - no biggie).

( returnType (*functionPointerToAdd)(T1) ) 

This is the arguments to the lambda. This means that the lambda should be called (!) with a function pointer of the type returnType(*)(T1). That's not what you want - you want it to be called with T1, T2, T3.

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

This defines the return type of the lambda - and only that. You're now saying that it has to return a function pointer, to a function returning a returnType and taking a T1, T2 and T3 as argument. The lambda type would then be

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

, or a function that takes a function pointer as argument and that returns a function pointer. Yes, it's overly complex and unreadable.

{ functionPointerToAdd(T1); };

This finally is the contents of the lambda and the reason for your error. You're passing the type T1 as argument to the function pointer.

Suggestion for fixing it (as the syntax is horribly complex - I hope the above text will help you with why I changed what:

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

Feel free to ask why & how.


I think the error is exactly what the compiler says: your call functionPointerToAdd(T1) doesn't make sense. T1 is a type, not a variable. Your lambda only takes a function pointer as an argument, but no actual object to call the function with!

Also, what's the lambda supposed to return? If its only purpose is to return functionPointerToAdd(...), shouldn't its return type just be returnType?

Maybe something like this (but I don't understand your requirements fully):

typedef returnType (*myFP)(T1);

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

I'm also getting rid of the "capture everything by reference" ([&]) because you don't seem to be using any non-local variables.

Edit: Oh wait, I see, you want to add myFunc to the vector. So you want to bind your given pointer to a lambda whose body consists of calling the function. OK, let's see:

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

But I doubt that you can do that, because lambdas that capture from the environment are not convertible to naked function pointers, I believe. We really need a proper function object for your situation, methinks.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号