只读类变量(C ++)和运算符重载

时间:2017-07-03 23:01:44

标签: c++ templates operator-keyword

请使用以下代码:

#include <string>
#include <iostream>

template <class T, class U>
class readonly
{
  friend U;
  private:
    T data;
    T operator=(const T& arg) {data = arg; return data;}
    T operator+=(const T& arg) {data = data + arg; return data;}
    T operator-=(const T& arg) {data = data - arg; return data;}
    T operator*=(const T& arg) {data = data * arg; return data;}
    T operator/=(const T& arg) {data = data / arg; return data;}
  public:
    operator const T&() const {return data;}
};

class myClass
{
  private:
    typedef readonly<int, myClass> RO_int;
    typedef readonly<std::string, myClass> RO_string;

  public:
    RO_int x;
    RO_string y;

    void f()
    {
      x = 55;
      y = "Howdy";
      std::cout << x << "\n\n";  // compiles fine
      std::cout << y << "\n\n";  // compile error
    }
};

我使用这些模板类来确保某些公共变量xy是&#34;只读&#34;在类之外,但可以在类本身内进行修改。除了我试图显示字符串类型的变量y的最后一行之外,此代码中的所有内容都编译得很好。我不明白为什么我能够显示x而不是y。如果我需要重载<<运算符,为什么我必须为std::string而不是int执行此操作?

1 个答案:

答案 0 :(得分:3)

首先,但不是您的问题,您的运营商应该返回readonly&T&而不是T。不要像那样违反惯例。

现在给出一个实际答案。

这是因为operator<<使用string是模板,模板函数在模式匹配时不考虑转换。获取<<的{​​{1}}不是模板,因此会考虑转化。

我们可以通过创建一个无法转换的int来解决此问题:

只需添加

operator<<

到你的friend std::ostream& operator<<(std::ostream& os, readonly const& self) { return os<<self.data; } 类型,事情应该有效。这将通过ADL找到。

我们可以通过模板获取第一个参数并检查readonly是否有效以及第一个参数是从<<派生,还是类似地针对第二个参数,使SFINAE之类的版本变得更加漂亮。