user173342
user173342

Reputation: 1840

Lambda function failing to call static functions of a function template parameter

Ok, so I have something setup basically like this:

template<typename T> void example()
{
 std::function<int (byte*)> test = [=](byte* start) -> int
 {
  return T::magic(start);
 }
}

Ignoring how "unclean" making these naked calls is, it also doesn't compile, giving these errors:

'T' : is not a class or namespace name
'magic': identifier not found

Is there any way to be able to make a call on the generic typename T, assuming I will always be calling example() with a class that has the function magic(byte* start)? Surely I don't have to redeclare this template function for every single class that will be doing this.

I'm doing this in VC++ 2010, and it appears it may be a compiler bug. Any possible workarounds?

Upvotes: 6

Views: 2392

Answers (3)

sehe
sehe

Reputation: 393064

I reproduced the problem with VS2010. You need to call the example function, though:

#include <functional>

struct SomeT { static int magic(unsigned char*) { return 42; } };

template<typename T> void example()
{
    std::function<int (unsigned char*)> test = [=](unsigned char* start) -> int
    {
        return T::magic(start);
    };
}

int main()
{
    example<SomeT>();
}

Update based on a comment by the OP:

This works:

#include "stdafx.h"
#include <functional>

struct SomeT { static int magic(unsigned char*) { return 42; } };

template<typename T> void example()
{
    auto func = T::magic;
    std::function<int (unsigned char*)> test = [=](unsigned char* start) -> int
    {
        return func(start);
    };
}

int main()
{
    example<SomeT>();
}

I have been looking for workarounds, but none working yet, I tried up to and including this nice permutation, but no luck yet:

template<typename T> void example()
{
    static const T* workaround;
    std::function<int (unsigned char*)> test = [=](unsigned char* start) -> int
    {
        typedef decltype(*workaround) innerT;
        return innerT::magic(start);
    };
}

Tough one this...

Upvotes: 3

Benjamin Lindley
Benjamin Lindley

Reputation: 103713

The only error there is the missing semi-colon. Once that is fixed, it works fine.

#include <iostream>
#include <functional>

typedef unsigned char byte;

template<typename T> void example()
{
    std::function<int (byte*)> test = [=](byte* start) -> int
    {
        return T::magic(start);
    }; // <--------------------------------- You were missing that
}

struct Foo {
    static int magic(byte*);
};

int Foo::magic(byte* start)
{
    std::cout << "magic\n";
}

int main()
{
    example<Foo>();
}

http://ideone.com/dRdpI

As this appears to be a bug in VC10's lambda implementation, a possible workaround is to create a local functor class:

template<typename T> void example()
{
    struct Foo {
        int operator()(byte * start) { return T::magic(start); }
    };

    std::function<int (byte*)> test = Foo();    
}

Upvotes: 4

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361472

I'm sure you're doing something wrong, because I'm able to call a static method using the syntax T::f() inside the lambda:

#include <iostream>
#include <functional>
struct A
{
   static void f() { std::cout << "called" << std::endl; }
};

template<typename T> 
void example()
{
  std::function<void()> test = [=]() { T::f(); };
  test();
}
int main() {
        example<A>();
        return 0;

}

Demo : http://ideone.com/IPakS

So please post more info. Till this is the answer. Try compare your code with this and see if you're doing something terribly wrong.

If you're using GCC, did you compile your code with -std=c++11 option?

Upvotes: 0

Related Questions