1

Using c++11 I want to create a class that uses a lambda as part of a calculation.

//contrived sample of potential usage
void random_class::some_function(void)
{
 auto an_object = new my_custom_object(5, [this](){ return random_class_member * 5; });
 an_object.do_some_processing();
 random_class_member++;
 an_object.do_some_processing();
}

I am not quite sure how to go about declaring and defining my_custom_object.

class my_custom_object
{
public:
 template <typename Proc>
 my_custom_object(int a, Proc p)
 {
  privatea = a;
  privatep = p;
 }
 void do_some_processing()
 {
  privatea += privatep();
 }
private:
 int privatea;
 Proc privatep;
}

unknown type name 'Proc'

5
  • There is no relation between them Commented Jun 30, 2020 at 16:44
  • 4
    You may want to look at std::function for storing the lambda. Commented Jun 30, 2020 at 16:44
  • You need to template the entire class, not just the constructor Commented Jun 30, 2020 at 16:49
  • How would I use my_custom_object with a lambda if the entire class is templated? What would random_class::some_function look like? Commented Jun 30, 2020 at 16:50
  • why privatea = a? Why not this.a = a? Or my_custom_object(int a, std::function<int(void)> p) : a(a), p(p) {} Commented Jun 30, 2020 at 16:54

2 Answers 2

5

There are two approaches you could take.

Use a type-erased std::function

For example:

class my_custom_object {
public:
    my_custom_object(int a, std::function<void()> p)
    {
        privatea = a;
        privatep = p;
    }
    void do_some_processing()
    {
        privatea += privatep();
    }

private:
    int privatea;
    std::function<void()> privatep;
};

This allows my_custom_object to accept any function-like thing that accepts no parameters. There is some performance overhead though, since the calls to privatep have to be resolved at runtime. This is likely negligible, but it could matter if this is happening in a tight loop in a performance-critical section of your program though.

The call site would look exactly as you have it now:

void random_class::some_function(void)
{
   my_custom_object an_object{5, [this](){ return random_class_member * 5; }};
   an_object.do_some_processing();
   random_class_member++;
   an_object.do_some_processing();
}

Template my_custom_object on the type of function it holds.

For example:

template <typename Proc>
class my_custom_object {
public:
    my_custom_object(int a, Proc p)
    {
        privatea = a;
        privatep = p;
    }
    void do_some_processing()
    {
        privatea += privatep();
    }

private:
    int privatea;
    Proc privatep;
};

This will allow your calls to privatep to be resolved statically at compile time, which may have slightly better performance than using std::function. This does mean that the type of Proc is now part of the type of my_custom_object though, so it's a bit less flexible in some situations.

Since C++17 added class template argument deduction, the call site would look exactly the same:

void random_class::some_function(void)
{
   my_custom_object an_object{5, [this](){ return random_class_member * 5; }};
   an_object.do_some_processing();
   random_class_member++;
   an_object.do_some_processing();
}

If you have to use a pre-C++17 compiler you'll have to specify the template parameter to my_custom_object explicitly:

void random_class::some_function(void)
{
   auto func = [this](){ return random_class_member * 5; };
   my_custom_object<decltype(func)> an_object{5, func};
   an_object.do_some_processing();
   random_class_member++;
   an_object.do_some_processing();
}
Sign up to request clarification or add additional context in comments.

Comments

2

If the signature of the lambda is fixed you can remove the template and use std::function<ReturnType(parameters)>. In your case

using Proc = std::function<int(void)>;

should work. Then you can pass a lambda that takes no arguments and returns an int.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.