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

时间:2015-01-01 10:21:53

标签: c++

我正在尝试在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,我为T定义了运算符,在本例中为int

4 个答案:

答案 0 :(得分:1)

您实例化了myreference<int>

类型的对象
myreference<int> myref;

因此赋值运算符专用于参数类型int &。但是,您试图识别可能绑定到常量引用的临时对象。因此赋值运算符必须专门用于参数类型const int &

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

myreference<const int> myref1;

myref1 = 42;

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

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

答案 1 :(得分:1)

您的问题大于编译器错误。编译器错误告诉您存在基本设计错误。

您的引用=都充当引用重新绑定器(更改附加空引用的内容)和赋值(连接附加到的事物的值)。这些是基本不同的操作。

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

但是使用一个函数时,传递的参数必须是 - 并且这些类型不匹配。值可读是T const&。可绑定值为T&

如果您将类型更改为T const&,则重新绑定data = &t将失败。如果您将42之类的临时文件传递给=,则会重新附加重新绑定,并在调用行的末尾变为无效。同样,如果您为其分配int const foo = 3;

你可以修复&#39;这有一个const_cast,但只是抛出了检查窗口的类型:它隐藏了未定义的行为,而不是给你一个诊断。

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

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

您的参考可能更好地称为“指针”。在这一点上。

答案 2 :(得分:0)

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

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

快乐的编码。

答案 3 :(得分:0)

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

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

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

此外,在代码中进行更改以使其工作。

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