带有模板化参数的模板化 class 运算符重载特化

Templated class operator overload specialization with templated argument

我有一个模板化的 class,我在其中重载了加法和输出运算符,并且我有一个特定的专业化也被模板化了。我还没有找到如何执行此操作的任何示例,最后我遇到了链接错误,所以我想知道这是否可能。

// Point.hpp
namespace crypto {
// Forward declarations for template specialization
template<class T> class FieldElement;
template<class T> class Point;
template<class T> std::ostream& operator<<(std::ostream& out, const Point<T>& point);
template<class T> std::ostream& operator<<(std::ostream& out, const Point<FieldElement<T>>& point);
template<class T> Point<T> operator+(const Point<T>& lhs, const Point<T>& rhs);
template<class T>
Point<FieldElement<T>> operator+(const Point<FieldElement<T>>& lhs, const Point<FieldElement<T>>& rhs);

template<class T> class Point
{
  public:
    Point(std::optional<T> x, std::optional<T> y, T a, T b);
    ~Point() = default;

    template<class U> friend Point operator+(const Point& lhs, const Point& rhs);
    template<class U> friend std::ostream& operator<<(std::ostream& os, const Point<U>& element);

    std::optional<T> X;
    std::optional<T> Y;
    T A;
    T B;
};

template<class T> Point<T> operator+(const Point<T>& lhs, const Point<T>& rhs)
{
    ...
}

template<class T> std::ostream& operator<<(std::ostream& os, const Point<T>& point)
{
    // Write Point to stream
    if (!point.X)
        os << "Point(infinity)";
    else
        os << "Point(" << point.X.value() << "," << point.Y.value() << ")_" << point.A << "_" << point.B;

    return os;
}
}

以及专业:

// Point.cpp
namespace crypto {

template<class T> Point<FieldElement<T>> operator+(const Point<FieldElement<T>>& lhs, const Point<FieldElement<T>>& rhs)
{
    ...
}

template<class T> std::ostream& operator<<(std::ostream& os, const Point<FieldElement<T>>& point)
{
    if (!point.X)
        os << "Point(infinity)";
    else
    {
        os << "Point(" << point.X.value().Number << "," << point.Y.value().Number << ")_" << point.A.Number << "_"
           << point.B.Number << " FieldElement(" << point.X.value().Prime << ")";
    }

    return os;
}
}

调用代码:

// Test.cpp
TEST(IntegrationTests, PointAdditionTests)
{
    auto prime = 223;
    auto a = FieldElement(0, prime);
    auto b = FieldElement(7, prime);
    auto x1 = FieldElement(192, prime);
    auto y1 = FieldElement(105, prime);
    auto x2 = FieldElement(17, prime);
    auto y2 = FieldElement(56, prime);
    auto p1 = Point<FieldElement<int>>(x1, y1, a, b);
    auto p2 = Point<FieldElement<int>>(x2, y2, a, b);
    std::cout << p1 + p2 << std::endl;
}

最后是我的链接错误: clang++ -o 构建

d/bitcoin/crypto/CryptoLibTests -pthread build/bitcoin/crypto/tests/CryptoIntegrationTests.o build/bitcoin/crypto/tests/FieldElementTests.o build/bitcoin/crypto/tests/PointTests.o -Lbuild/lib -lpthread -lBtcCrypto -lgtest -lgtest_main
Undefined symbols for architecture x86_64:
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >& crypto::operator<<<int>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, crypto::Point<crypto::FieldElement<int> > const&)", referenced from:
      IntegrationTests_PointAdditionTests_Test::TestBody() in CryptoIntegrationTests.o
  "crypto::Point<crypto::FieldElement<int> > crypto::operator+<int>(crypto::Point<crypto::FieldElement<int> > const&, crypto::Point<crypto::FieldElement<int> > const&)", referenced from:
      IntegrationTests_PointAdditionTests_Test::TestBody() in CryptoIntegrationTests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
scons: *** [build/bitcoin/crypto/CryptoLibTests] Error 1
scons: building terminated because of errors.

感谢@paddy,答案是将专业化移动到头文件中。然后上面的实现工作