带有模板化参数的模板化 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,答案是将专业化移动到头文件中。然后上面的实现工作
我有一个模板化的 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,答案是将专业化移动到头文件中。然后上面的实现工作