-1

I have a header file declaring a method, and a code file with the implementation. On compile, the compiler errors out with 'undefined reference to...'. If I copy the implementation of the method to the header, it then tells me the method is being redefined in the code file. Surely if it can find the method in the cpp file to call a duplicate, then it can use it. Since it can't be found, adding it to the header shouldn't cause a redefinition.

All headers are protected. In the code below, if I uncomment the header implementation, the method is redefined, if I leave it commented, the method is undefined. If I use only the header implementation, everything compiles fine but is bad architecture. The cpp file is being correctly copied to the output folder. Example code:

  • test.ino
  • math.h
  • math.cpp

test.ino

#include "math.h"

void setup() {
  int result = Math::Double((int)2);
}

void loop() {}

math.h

#ifndef MATH_H
#define MATH_H

namespace Math {
  template <typename U>
  U Double(U value);

//  template <typename U>
//  U Interpolate(U value) {
//    return value * 2;       ​
//  ​}

}

#endif

math.cpp

#include "math.h"

template <typename U>
U Math::Double(U value) {
  return value * 2;       ​
}
J Collins
  • 2,106
  • 1
  • 23
  • 30

1 Answers1

2

You have a few C++ syntax errors in your code.

  1. Templates have to be declared and defined inside header files (there is rare syntax that provides an exception to this, but I won't discuss that here).
  2. You are missing parentheses before your 'loop' function definition.
  3. You are declaring your Double parameter with the name "value" but then attempting to use it with the name "result"

Here's the corrected code:

EDIT Changed this to separate template declarations/definitions. The original answer will be below the row of asterisks after this revised answer.

math.h

#ifndef MATH_H
#define MATH_H

namespace Math {
  template <typename U>
  U Double(U value);
}

#include "math_ipp.h"
#endif

math_ipp.h

#ifndef MATHIPP_H
#define MATHIPP_H
#include "math.h"

namespace Math {
  template <typename U>
  U Double(U value) {
    return value * 2;
  }
}

#endif

test.ino

#include "math.h"

void setup() {
  int result = Math::Double((int)2);
}

void loop() {}

********** ORIGINAL ANSWER BELOW math.h

#ifndef MATH_H
#define MATH_H

namespace Math {
  template <typename U>
  U Double(U value) {
    return value * 2;
  }
}

#endif

test.ino

#include "math.h"

void setup() {
  int result = Math::Double((int)2);
}

void loop() {}
Alex
  • 877
  • 5
  • 10
  • I've updated my sample code with your identified issues. However I see you have reinstated the implementation in the .h file. Was this intended? I can't imagine this being the final intent. What would the .cpp file look like in your instance? – J Collins Feb 21 '22 at 14:55
  • Don't define Double in the .cpp file, remove it completely. Don't define template functions in CPP files. Templates require special syntax – Alex Feb 21 '22 at 15:01
  • Surely you don't advocate only using header files. There must be a reasonable solution to implementations of templates across header and code files, could you help me understand what that might look like for this simple example? – J Collins Feb 21 '22 at 15:03
  • No, this is normal for templates. If you really want to separate template function/class declarations from their definitions, then must use another header file. The naming convention for this would be math.h for template declarations and math_ipp.h for template definitions – Alex Feb 21 '22 at 15:04
  • 1
    This question discusses the reasons why a template needs to be implemented in the header and provides a limited work around: [https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – drescherjm Feb 21 '22 at 15:08
  • Stunned. Fair enough, don't suppose there are any code examples of this or style conventions you're aware of? – J Collins Feb 21 '22 at 15:08
  • I'll post one in a second – Alex Feb 21 '22 at 15:09
  • 1
    @JCollins I revised my answer to show how to separate template declarations from definitions – Alex Feb 21 '22 at 15:12
  • Thanks Alex, great answer, accepted. – J Collins Feb 21 '22 at 15:25