c ++即使定义了运算符也没有运算符匹配

c++ no operator matches even when operator is defined

我正尝试在 C++ 中实现自定义引用。我要实现的是有引用,不需要在创建的时候设置。看起来像这样

template<typename T>
class myreference
{
    public:
        myreference() : data(), isset(false) { }
        explicit myreference(const T& _data) : data(&_data), isset(true) { }
        myreference<T>& operator=(T& t)
        {
            if (!isset)
            {
                isset= true;
                data = &t;
            }
            else
                *data = t;
            return *this;
        }

        operator T() const { return *data; }
        operator T&() { return *data; }
    private:
        T* data;
        bool isset;
};

它工作正常。我可以做到这一点,除了最后一句话。

myreference<int> myref;
int data = 7, test = 3;
myref = data; // reference is set
myref = test; // data is now 3
int& i = myref;
i = 4; // data is now 4
cout << myref; // implicit int conversion
myref = 42; // error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int'

完全错误

error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)
1>          d:\...\main.cpp(33): could be 'myreference<int> &myreference<int>::operator =(const myreference<int> &)'
1>          d:\...\main.cpp(16): or       'myreference<int> &myreference<int>::operator =(T &)'
1>          with
1>          [
1>              T=int
1>          ]
1>          while trying to match the argument list 'myreference<int>, int'

我在网上搜索并发现了类似的错误(使用 不同的 运算符),结果是将运算符放在它的类之外,但这对于 operator= 出于某些(我相信很好的)原因。我的问题是,编译器在抱怨什么?参数列表是 myreference<int>, int 并且我为 Ts 定义了运算符,在这种情况下,它是 int.

由于赋值运算符需要变量(在本例中为整数),因此不允许将某个值 (42) 传递给它。 所以使用像

这样的整数
int x=42;
myref=x;

编码愉快。

myreference<T>& operator=(T& t)
myref = 42;

非常量引用不能绑定到临时引用。您可以将其更改为通过 const 引用获取参数。

myreference<T>& operator=(const T& t)          

此外,请更改您的代码以使其正常工作。

data = &t;                         <<< Replace this
data = const_cast<T*>(&t);         <<< with this. 

您实例化了一个 myreference<int>

类型的对象
myreference<int> myref;

所以赋值运算符专门针对参数类型int &。但是,您正在尝试分配一个可能绑定到常量引用的临时对象。所以赋值运算符必须专门用于参数类型 const int &.

因此您需要定义另一个 myreference<const int> 类型的对象,代码至少会被编译。例如

myreference<const int> myref1;

myref1 = 42;

然而在任何情况下,代码都会有未定义的行为,因为执行此赋值语句后临时对象将被删除,数据成员数据将具有无效值。

通常这样的 claases 禁止使用临时对象来避免未定义的行为。

你的问题比编译器错误更大。编译器错误告诉你你有一个基本的设计错误。

您的引用 = 既充当引用重新绑定器(更改空引用附加到的对象)又充当赋值(更改附加对象的值)。这些是根本不同的操作。

一个需要一个可以稍后修改(重新绑定)的长期值,另一个需要一个可以从中读取的值(赋值)。

然而,对于一个函数,传递的参数必须是其中之一——而且这些类型不匹配。可读值是 T const&。可绑定值是 T&.

如果您将类型更改为 T const&,则重新绑定 data = &t 会失败,这是应该的。如果你传递一个临时的,比如 42,到你的 =,一个重新绑定附加到它,并在调用行的末尾变得无效。同样,如果您将 int const foo = 3; 分配给它。

您可以 'fix' 使用 const_cast,但这只会抛出检查 window 的类型:它隐藏了未定义的行为,而不是给您诊断。

另一方面,T& 参数不能绑定到 42 临时值,也不能绑定到常量 const int foo = 3。这在重新绑定的情况下很好,但使赋值有点无用。

如果您有两个操作,=(T const &).rebind(T&),您的问题就会消失。作为副作用, = 未设置时是未定义的行为。不过以前基本都是这样。

此时您的参考文献最好称为 'pointer'。