Error compiling codes: undefined reference

AppData\Local\Temp\ccsbCXFP.ltrans0.ltrans.o: In function `global constructors keyed to 65535_0_ArrayList.cpp.o.2153':
<artificial>:(.text.startup+0x46): undefined reference to `ArrayList<int>::ArrayList(int)'
<artificial>:(.text.startup+0x50): undefined reference to `ArrayList<int>::ArrayList(int)'
<artificial>:(.text.startup+0x60): undefined reference to `Device<float>::Device(ArrayList<int>)'
collect2.exe: error: ld returned 1 exit status

exit status 1

Compilation error: exit status 1

ArrayList.h

template<typename E>
class ArrayList {
private:
    int _size;
    E *const _array = {};
    void grow(int minCapacity);
    void ensureExplicitCapacity(int minCapacity);
    void ensureCapacityInternal(int minCapacity);

public:
    ArrayList();
    ArrayList(int initialCapacity);
    ArrayList(E *const initialArray);

ArrayList.cpp

template<typename E>
ArrayList<E>::ArrayList(int initialCapacity) {
    _array = new E[initialCapacity];
}
template<typename E>
ArrayList<E>::ArrayList(E *const initialArray) {
    _array = initialArray;
}

your class definition is missing the trailing }; and the .cpp would need to #include "ArrayList.h"

you also have to think it terms of who owns the array and add a destructor. May be something like this

.h

#ifndef __ARRAYLIST___
#define __ARRAYLIST___
#include <Arduino.h>

template<typename E>
class ArrayList {
private:
    int _size;
    E* _array;  // Removed const here as you want to change it
    void grow(size_t minCapacity);
    void ensureExplicitCapacity(size_t minCapacity);
    void ensureCapacityInternal(size_t minCapacity);

public:
    ArrayList(size_t initialCapacity = 10);
    ArrayList(E* const initialArray);
    ~ArrayList();  // Add a destructor to release allocated memory
};

#endif

.cpp

#include "ArrayList.h"

template<typename E>
ArrayList<E>::ArrayList(size_t initialCapacity) : _size(0), _array(new E[initialCapacity]) {}

template<typename E>
ArrayList<E>::ArrayList(E* const initialArray) : _size(0), _array(initialArray) {}

template<typename E>
void ArrayList<E>::grow(size_t minCapacity) {
    // Implement the grow function
}

template<typename E>
void ArrayList<E>::ensureExplicitCapacity(size_t minCapacity) {
    // Implement the ensureExplicitCapacity function
}

template<typename E>
void ArrayList<E>::ensureCapacityInternal(size_t minCapacity) {
    // Implement the ensureCapacityInternal function
}

template<typename E>
ArrayList<E>::~ArrayList() {
    delete[] _array;  // Release the allocated memory in the destructor
}

you'll have to explore exactly what it is you want from the constructor using an array
see also The rule of three/five/zero ➜ make the right decisions there, might need

    ArrayList(size_t initialCapacity = 10);
    ArrayList(const ArrayList& other);
    ArrayList(ArrayList&& other) noexcept;
    ArrayList& operator=(const ArrayList& other);
    ArrayList& operator=(ArrayList&& other) noexcept;
    ~ArrayList();

Thanks. I've encountered another similar problem.

/var/folders/x7/p119gjkx60n54k0hjx6p26br0000gn/T//ccPsrUEV.ltrans0.ltrans.o: In function `global constructors keyed to 65535_0_ArrayList.cpp.o.1815':
<artificial>:(.text.startup+0x60): undefined reference to `Device<float>::Device(int*)'

Device.h

#ifndef DEVICE_H
#define DEVICE_H


#include "Arduino.h"
#include "ArrayList.h"

template<typename T>
class Device {
protected:
    String _tag = "";
    ArrayList<String> _parentTags = new ArrayList<String>();
    int *const _pins;

public:
    Device(int *const pins);
    ~Device();
    void tag(String tag);
    String tag();
    void parentTags(ArrayList<String> parentTags);
    ArrayList<String> parentTags();
    void pinsCheck(int requiredNum);
    void initialize(String *parentTags);
    T read();
    void write(T payload);
    void close();
};
bool pulse(int pin);


#endif // DEVICE_H

Device.cpp

#include "Device.h"

template<typename T>
Device<T>::Device(int *const pins) : _pins(pins) {}
template<typename T>
Device<T>::~Device<T>() {
    delete[] _pins;
}
template<typename T>
void Device<T>::tag(String tag) {
    _tag = tag;
}
template<typename T>
String Device<T>::tag() {
    return _tag;
}
template<typename T>
void Device<T>::parentTags(ArrayList<String> parentTags) {
    _parentTags = parentTags;
}
template<typename T>
ArrayList<String> Device<T>::parentTags() {
    return _parentTags;
}
template<typename T>
void Device<T>::pinsCheck(int requiredNum) {
    if (sizeof(_pins) != requiredNum)
        throw value_error(format("This device only takes in {} pins", requiredNum));
}
bool pulse(int pin) { return digitalRead(pin) == LOW; }

WheelSpeedSensor.h

#ifndef WHEELSPEEDSENSOR_H
#define WHEELSPEEDSENSOR_H

#include "Device.h"

#define BOUNCETIME 20

class WheelSpeedSensor : public Device<float> {
protected:
    long _t1, _t2;

public:
    WheelSpeedSensor(int *const pins);
    void initialize();
    float read();
};


#endif // WHEELSPEEDSENSOR_H

WheelSpeedSensor.cpp

#include "WheelSpeedSensor.h"

WheelSpeedSensor::WheelSpeedSensor(int *const pins) : Device<float>(pins) {
}

void WheelSpeedSensor::initialize() { pinMode(_pins[0], INPUT); }

float WheelSpeedSensor::read() {
    if (millis() - _t2 > BOUNCETIME && pulse(_pins[0])) {
        _t1 = _t2;
        _t2 = millis();
    }
    return 60 / (_t2 - _t1);
}

All the template functions have to be in the .h file or they aren't seen from other compilation units.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.