-2

How to dynamically create an array with this class (this is Teensy Step library for arduino):

class StepControl : IPitHandler, IDelayHandler
{
public:
...
   StepControl();
   template<size_t N> void move(Stepper* (&motors)[N], float relSpeed = 1);
...

and then this is usage of this class that works 100% but is static:

 Stepper J1(0, 1), J2(2, 3), J3(4, 5), J4(6, 7), J5(8, 9), J6(10, 11);
 StepControl <> controller;

 Stepper *robot[] = {&J1,&J2,&J3,&J4,&J5,&J6};
 controller.move(robot);

I want to do sth like this but create array dynamically:

 Stepper J1(0, 1), J2(2, 3), J3(4, 5), J4(6, 7), J5(8, 9), J6(10, 11);
 StepControl <> controller;

 int j = 4
 Stepper *robot[j];
 robot[0]=&J1;
 robot[1]=&J2;
 robot[2]=&J2;
 robot[3]=&J2;
 controller.move(robot);

result: error: no matching function for call to 'StepControl<>::move(Stepper* [j])'

How to do this?

5
  • 1
    I suggest you first to figure out which language you are actually working with. Commented Sep 14, 2018 at 17:42
  • 3
    Use a std::vector to make your life easier. Commented Sep 14, 2018 at 17:42
  • 1
    std::vector<Stepper*> robot= {&J1,&J2,&J3,&J4}; // result error: no matching function for call to 'StepControl<>::move(std::vector<Stepper*>&)' Commented Sep 14, 2018 at 17:52
  • Note that an plain array of compile-time size Stepper* x[N] is not the same as a mystery-sized Stepper* x pointer array. Try declaring robot as Stepper *robot[4]; Commented Sep 14, 2018 at 17:54
  • @alterigel Ok but the size of array will change int j=4; is just example. If I use Stepper *robot[4]; size will be static(4xStepper). How to use it if I would like to add 2 more dynamically but not to use "oversized" array? Commented Sep 14, 2018 at 18:05

2 Answers 2

2

Currently, your StepControl::move() method is written to only accept arrays whose size is known at compile time. This means that if the compiler can figure out the size of an array, as in:

// size is inferred at compile time to be 6
Stepper* robot[] = {&J1,&J2,&J3,&J4,&J5,&J6};

then the compiler can successfully match controller.move(robot); to the following template instantiation:

void move<>(Stepper* (&motors)[6], float relSpeed = 1);

But without knowing at compile time what your array size is going to be, the compiler can't match a call to move to a particular template instantiation. When you write

int j = 4;
Stepper *robot[j];

Because j is not a compile-time constant, robot is actually a dynamically sized stack array which is non-standard. Some compilers allow it, but a consequence is that the size of robot cannot be known at compile time.


To fix this, you could either always be certain of your array size at compile time, as in:

if (needsToBeSix){
    Stepper *robots[6] = ...;
    controller.move(robots);
} else if (needsToBeFour){
    Stepper *robots[4] = ...;
    controller.move(robots);
}

Or, if you really need dynamically-sized arrays, use std::vector:

class StepControl {
    ...
    void move(std::vector<Stepper*>& motors, float relSpeed = 1){
        // size can be queried at runtime as follows
        const size_t N = motors.size();
        // rest of method;
    }
    ...
}

...

std::vector<Stepper*> robot { &J1, &J2, &J3, &J4 };
if (needTwoMore){
    robot.push_back(&J5);
    robot.push_back(&J6);
}
controller.move(robot);
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for very good explanation! It is very clear now. One more thing comes to my mind. If the maximum size of array is known for eg. size '10 x Stepper'. Can I declare array of known maximum size and then dynamically resize it (shrink it)? Stepper *robots[10] = {}; then robot[0]=&J1;... and then malloc or something?
Doing that would require additional logic to track and check the size of your array. vector already keeps track of its own size and manages its storage automatically without you having to think about it. As an aside, you should prefer a standard container or pointer wrapper (like vector, array, shared_ptr or unique_ptr) to new, and you should very much prefer new/delete to malloc/free, which won't call constructors and destructors!
-1

Like the idea of alter igel. Will implement the vector interface in the library so that you can use it as proposed.

1 Comment

Thanks for the shout-out, but how does this answer Kristof's question? If you meant to add a comment, you may want to read meta.stackexchange.com/questions/214173/…

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.