0

I have a class Komp where I have a user-defined literal constexpr Komp operator""_i(long double x) to produce a komp object from e.g Komp k = 1 + 5.0_i;.

This works fine in komp.cpp's main(), however when I write the same exact statement in testing.cpp (where komp.h is included) I get the error below. Every other function in komp.h works fine in testing.cpp. I expected the user-defined literal to be included as the other functions are.

Why is the user-defined literal not working in testing.cpp while other functions are?

The error:

Undefined symbols for architecture x86_64:
  "operator"" _i(long double)", referenced from:
      MyTestSuite::test5() in komp_testrunner-d3c20f.o
ld: symbol(s) not found for architecture x86_64

// komp.cpp
class Komp {
    private:
        double val1;
        double val2;
    public: 
        // ... Bunch of member-function headers
        constexpr Komp(const double x, const double y) : val1(x), val2(y) {}
        double v1() {return val1;}
        double v2() {return val2;}
};
// ... Bunch of member and non-member functions.
Komp operator+ (const double lhs, const Komp rhs) { // overloads + operator for: double + Komp
    return Komp(lhs+rhs.v1(), rhs.v2());
}
constexpr Komp operator""_i(long double x) { // To match i.e Komp k = 1 + 2.3_i
    return Komp(0.0, x);
}
constexpr Komp operator""_i(unsigned long long x) { // To match i.e Komp k = 1 + 2_i
    return Komp(0.0, x*1.0);
}
int main() { // Only here temporarily for testing purposes
    Komp k = 1 + 2.0_i; // Works here
}
// komp.h
#include <string>
#ifndef KOMP_H
#define KOMP_H
class Komp
{
    public: 
        double val1;
        double val2;
        // ...
        Komp(const double x, const double y);
};
// ...
Komp operator+ (const double lhs, const Komp rhs);
Komp operator ""_i(long double arg);
Komp operator ""_i(unsigned long long arg);
#endif  
#include "komp.h"
#include <cxxtest/TestSuite.h>

class Testing : public CxxTest::TestSuite {
  public:
    void literalTest () {
      Komp c = 3.0 + Komp(2.0, 2.0); // Works fine. No problem with overloading + operator
      Komp b = 5.0 + 2.0_i; // Causing an error
      Komp c = Komp(1.0, 2.0);
      TS_ASSERT(b != c); 
    }
};
StijnVanDijk
  • 3
  • 1
  • 3
  • How come your Komp class is defined in both cpp and .h file? – SergeyA Jul 28 '20 at 14:54
  • The code defines the class `Komp` in both the .h and the .cpp file. That's not the usual convention; it's legal, but the usual approach is for the .cpp file to `#include` the .h file. That would fix one problem in this code, that the two definitions of `Komp` are different. – Pete Becker Jul 28 '20 at 15:45

1 Answers1

1

This function declaration:

Komp operator ""_i(long double arg);

is the only one visible to testing.cpp, or any file that includes Komp.h. However, you have not defined this function anywhere.

Note that this definition:

constexpr Komp operator""_i(long double x) { // To match i.e Komp k = 1 + 2.3_i
    return Komp(0.0, x);
}

is constexpr, so it's a different function. Simply declare the function as constexpr as well in Komp.h.

Also, you have defined the Komp class in Komp.cpp, as well as Komp.h. This is technically legal, but only if both the definitions are identical. In your case, the definitions are different, which violates the one-definition-rule, which means your program has undefined behavior. You should define Komp only in Komp.h.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • Re: "if you change one definition, but not the other" -- in this case, that's already happened. The two definitions are not the same. – Pete Becker Jul 28 '20 at 15:46
  • @PeteBecker True, I didn't even notice that; I assumed OP had copy-pasted the definition. Thanks for the correction, edited the answer. – cigien Jul 28 '20 at 15:54