提问人:Chimess 提问时间:7/24/2023 最后编辑:Chimess 更新时间:7/24/2023 访问量:35
友元函数不可从模板类运算符重载中调用
Friend function not callable from template class operator overload
问:
我正在尝试设置一个用于表示 2-3D 向量的类。它是一个模板类,采用坐标类型(坐标的积分/点表示)和 Dim(维度数)作为其模板定义的一部分。
#pragma once
#include <iostream>
#include <array>
#include <type_traits>
#define DIM2 2
#define DIM3 3
typedef size_t Dimensions;
namespace Geo{
template<class Coordinate_type, Dimensions dim = DIM3>
class Vector{
static_assert(std::is_arithmetic<Coordinate_type>::value, "Vector class can only contain Integral or Floating point types");
static_assert(dim >= DIM2, "Vector dimension should be at least 2D");
// friends
// Functions
#if 1
template <class type, Dimensions d>
friend Vector<type, d> CrossProduct(const Vector<type, d>& first, const Vector<type, d>& second);
#else
friend Vector<Coordinate_type, dim> CrossProduct(const Vector<Coordinate_type, dim>& first, const Vector<Coordinate_type, dim>& second);
#endif
std::array<Coordinate_type, dim> coords;
public:
// Constructors
Vector() {}
// Array Constructor
Vector(std::array<Coordinate_type, dim> _coords) : coords(_coords) {}
// 3D explicit constructor
Vector(Coordinate_type _x, Coordinate_type _y, Coordinate_type _z) : coords({_x, _y, _z}) {}
Vector(Coordinate_type _x, Coordinate_type _y) : coords({_x, _y}) {}
inline Vector<Coordinate_type, dim> operator+(const Vector<Coordinate_type, dim>& other);
inline Coordinate_type operator[](const int idx) const;
inline bool operator<(const Vector<Coordinate_type, dim>& other) const;
inline float Magnitude() const;
inline int GetDimension() const;
inline Vector<Coordinate_type, dim> Normalize() const;
};
template<class Coordinate_type, Dimensions dim>
inline Coordinate_type Vector<Coordinate_type, dim>::operator[](int idx) const{
return this->coords[idx];
}
template<class Coordinate_type, Dimensions dim>
inline Vector<Coordinate_type, dim> Vector<Coordinate_type, dim>::operator+(const Vector<Coordinate_type, dim>& other){
}
template<class Coordinate_type, Dimensions dim>
inline int Vector<Coordinate_type, dim>::GetDimension() const{ return this->coords.size(); }
template<class Coordinate_type, Dimensions dim>
inline float Vector<Coordinate_type, dim>::Magnitude() const{
float ret = 0;
for(int i = 0; i < this->coords.size(); i++){
ret += (*this)[i] * (*this)[i];
}
return std::sqrt(ret);
}
template<class Coordinate_type, Dimensions dim>
inline Vector<Coordinate_type, dim> Vector<Coordinate_type, dim>::Normalize() const{
// Store magnitude of vector
Coordinate_type magnitude = this->Magnitude();
// Copy vector
std::array<Coordinate_type, dim> temp;
for(int i = 0; i < this->GetDimension(); i++){
// Store the normalized component
temp[i] = (*this)[i]/magnitude;
}
return Vector<Coordinate_type, dim>(temp);
}
template<class Coordinate_type, Dimensions dim>
inline bool Vector<Coordinate_type, dim>::operator<(const Vector<Coordinate_type, dim>& other) const{
// Call to CrossProduct function
auto crossProd = CrossProduct( this->Normalize(), other.Normalize() );
// other logic ...
return true;
}
template<class Coordinate_type, Dimensions dim>
Vector<Coordinate_type, dim> CrossProduct( const Vector<Coordinate_type, dim>& first, const Vector<Coordinate_type, dim>& second){
// Definition here
return Vector<Coordinate_type, dim> (first.coords[0], first.coords[1], first.coords[2]);
}
}
-----------------------------------------
// main.cpp
int main() {
Geo::Vector<int, 3> v1(1,2,3);
Geo::Vector<int, 3> v2(2,4,6);
if(v1 < v2){
std::cout<< "v1 is less than v2" << std::endl;
}
return 0;
}
它具有用于比较向量的运算符重载。我只需要根据它们的大小来比较平行向量。
为了检查并行性,我使用叉积。定义为朋友。但是当我尝试从“<”运算符重载中调用它时,我总是收到错误。
错误内容如下:Undefined symbols for architecture arm64: "jmk::CrossProduct(jmk::Vector<int, 3ul> const&, jmk::Vector<int, 3ul> const&)", referenced from: jmk::Vector<int, 3ul>::operator<(jmk::Vector<int, 3ul> const&) const in main.o ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [main] Error 1
CrossProduct 函数可以从 main 调用,没有任何错误,但从运算符重载调用时。它抛出编译错误。
答:
您不关心提供最小的、可重复的示例,因此这是一个修复缺失部分的解决方案。
您声明了一个免费的好友函数。然后定义一个函数模板,并保持自由函数未定义。 启用与代码类似的代码,并获取链接器错误“未定义引用”。 启用修复。#if 0
CrossProduct()
#if 1
#include <iostream>
using Dimensions = int;
template <class Coordinate_type, Dimensions dim = 3>
class Vector {
#if 1
template <class type, Dimensions d>
friend Vector<type, d> CrossProduct(const Vector<type, d>& first,
const Vector<type, d>& second);
#else
friend Vector<Coordinate_type, dim> CrossProduct(
const Vector<Coordinate_type, dim>& first,
const Vector<Coordinate_type, dim>& second);
#endif
public:
// Constructors
Vector() {}
// 3D explicit constructor
Vector(Coordinate_type _x, Coordinate_type _y, Coordinate_type _z) {}
inline bool operator<(const Vector<Coordinate_type, dim>& other) const;
};
template <class Coordinate_type, Dimensions dim>
inline bool Vector<Coordinate_type, dim>::operator<(
const Vector<Coordinate_type, dim>& other) const {
// Call to CrossProduct function
auto crossProd = CrossProduct(*this, other);
// other logic ...
return true;
}
template <class Coordinate_type, Coordinate_type dim>
Vector<Coordinate_type, dim> CrossProduct(
const Vector<Coordinate_type, dim>& first,
const Vector<Coordinate_type, dim>& second) {
// Definition here
return first;
}
// main.cpp
int main() {
Vector<int, 3> v1(1, 2, 3);
Vector<int, 3> v2(2, 4, 6);
if (v2 < v1) {
std::cout << "v1 is less than v2" << std::endl;
}
return 0;
}
生活的例子:https://godbolt.org/z/ExYcjKErM
评论
note: (if this is not what you intended, make sure the function template has already been declared and add '<>' after the function name here)
warning: friend declaration 'Vector<Coordinate_type, dim> CrossProduct(const Vector<Coordinate_type, dim>&, const Vector<Coordinate_type, dim>&)' declares a non-template function [-Werror=non-template-friend]
operator<