所以我有一个模板类
TargetVar
,它本质上只是另一个变量的包装器,这样我就可以为所述变量设置目标值以及达到该值需要多少帧。每一帧,我都会在每个 TargetVar
上调用一个处理函数,将其值移向目标值。
这是课程:
class BaseTargetVar {
public:
BaseTargetVar() {
TargetVarManager::get_instance()->register_target_var(this); //TargetVarManager just iterates
//through all registered TargetVars and calls their process funcs
}
virtual ~BaseTargetVar() {
TargetVarManager::get_instance()->unregister_target_var(this);
}
virtual void process() {}
};
template <class T> class TargetVar : public BaseTargetVar {
public:
TargetVar() = default;
TargetVar(T& other) {
if (val != other) {
val = other;
frames = 0;
}
}
TargetVar(const T& other) {
if (val != other) {
val = other;
frames = 0;
}
}
void process() override {
if (frames) {
val += target_change_per_frame;
frames--;
if (!frames) {
val = target_val;
}
}
}
void set_target_val(T target_val, unsigned int frames) {
if (target_val == this->target_val) return;
this->target_val = target_val;
target_change_per_frame = target_val - val;
target_change_per_frame /= frames;
this->frames = frames;
}
void set_val(const T& val) {
this->val = val;
}
T get_val() const {
return val;
}
T* get_val_addr() const {
return &val;
}
T get_target_change_per_frame() const {
return target_change_per_frame;
}
unsigned int get_frames() const {
return frames;
}
private:
T val{};
T target_val{};
T target_change_per_frame{};
unsigned int frames = 0;
};
此类在我的项目中的主要用途之一是使用
TargetVar<glm::vec3>
来处理纹理的位置。因此,通常将 TargetVar<T>
与 T
进行比较(例如,将纹理的位置与屏幕上的位置进行比较,即 TargetVar<glm::vec3>
与 glm::vec3
),但比较 也很常见TargetVar<T>
与另一个 TargetVar<T>
(例如,将一个纹理的位置与另一个纹理的位置进行比较,即 TargetVar<glm::vec3>
与 TargetVar<glm::vec3>
)。为了使这更方便,我向 TargetVar
类添加了以下运算符重载:
template <typename U>
TargetVar<T>& operator=(const U& rhs) {
val = (T)rhs;
frames = 0;
return *this;
}
template <typename U>
bool operator==(const U& rhs) {
return val == rhs;
}
template <typename U>
bool operator!=(const U& rhs) {
return val != rhs;
}
template <typename U>
TargetVar<T>& operator=(const TargetVar<U>& rhs) {
if (this != &rhs) {
val = rhs.get_val();
frames = 0;
}
return *this;
}
template <typename U>
bool operator==(const TargetVar<U>& rhs) {
return val == rhs.get_val();
}
template <typename U>
bool operator!=(const TargetVar<U>& rhs) {
return val != rhs.get_val();
}
这个系统已经工作了几周,没有任何问题,但我注意到某些比较会导致 VS 中出现错误。例如:
TargetVar<glm::vec3> tv1 = glm::vec3(0.0);
TargetVar<glm::vec3> tv2 = glm::vec3(0.0);
if (tv1 != tv2) {
/*
Error E0350 - more than one operator "!=" matches these operands:
function template "bool TargetVar<T>::operator==(const U &rhs) [with T=glm::vec3]", with reversed arguments
function template "bool TargetVar<T>::operator==(const TargetVar<U> &rhs) [with T=glm::vec3]", with reversed arguments
function template "bool TargetVar<T>::operator!=(const U &rhs) [with T=glm::vec3]"
function template "bool TargetVar<T>::operator!=(const TargetVar<U> &rhs) [with T=glm::vec3]"
operand types are: TargetVar<glm::vec3> != TargetVar<glm::vec3>
*/
}
if (tv1 == tv2) {
/*
Error E0350 - more than one operator "==" matches these operands:
function template "bool TargetVar<T>::operator==(const U &rhs) [with T=glm::vec3]", with reversed arguments
function template "bool TargetVar<T>::operator==(const TargetVar<U> &rhs) [with T=glm::vec3]", with reversed arguments
function template "bool TargetVar<T>::operator==(const U &rhs) [with T=glm::vec3]"
function template "bool TargetVar<T>::operator==(const TargetVar<U> &rhs) [with T=glm::vec3]"
operand types are: TargetVar<glm::vec3> == TargetVar<glm::vec3>
*/
}
if (tv1 != tv2.get_val()) {
//No errors
}
if (tv1 == tv2.get_val()) {
//No errors
}
if (tv1.get_val() != tv2.get_val()) {
//No errors
}
if (tv1.get_val() == tv2.get_val()) {
//No errors
}
这些错误实际上并不会阻止程序编译,但我想知道为什么 VS 认为 tv1 到 tv2 的比较有问题,但 tv1 到 tv2.get_val() 比较没有问题。
此外,出于好奇,我删除了 != 运算符重载,以查看“使用反向参数”位是否会消失。它没有改变任何现有的错误,但它确实引入了以下错误,这些错误确实导致程序无法编译:
if (tv1 != tv2) {
/*
Error C2666 - 'TargetVar<glm::vec3>::operator ==': overloaded functions have similar conversions
*/
}
if (tv1 == tv2) {
/*
Error C2666 - 'TargetVar<glm::vec3>::operator ==': overloaded functions have similar conversions
*/
}
最终,程序按原样运行得很好,但我想知道为什么 VS 只在特定情况下出现问题,以及除了手动将 .get_val() 手动放入所有内容之外,我是否可以做任何事情我的操作。