-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?

Srini
  • 1,619
  • 1
  • 19
  • 34
Kristof
  • 23
  • 1
  • 1
    I suggest you first to figure out which language you are actually working with. – Eugene Sh. Sep 14 '18 at 17:42
  • 3
    Use a `std::vector` to make your life easier. – πάντα ῥεῖ Sep 14 '18 at 17:42
  • 1
    std::vector robot= {&J1,&J2,&J3,&J4}; // result error: no matching function for call to 'StepControl<>::move(std::vector&)' – Kristof Sep 14 '18 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];` – alter_igel Sep 14 '18 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? – Kristof Sep 14 '18 at 18:05

2 Answers2

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);
alter_igel
  • 6,899
  • 3
  • 21
  • 40
  • 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? – Kristof Sep 14 '18 at 19:43
  • 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! – alter_igel Sep 14 '18 at 21:11
-1

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

luni64
  • 321
  • 2
  • 8
  • 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 https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead – alter_igel Sep 28 '18 at 09:07