User-defined literal fails to include another file

89 views Asked by At

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); 
    }
};
1

There are 1 answers

2
cigien On

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.