【问题标题】:Make a Class variable const after declaration (run time) (with some class method)在声明后(运行时)创建一个类变量 const(使用一些类方法)
【发布时间】:2021-08-11 06:23:37
【问题描述】:

我有一个模板:

template<typename T>
struct Parameter {

    T value;
    std::string name;

    Parameter(std::string name, T value) : name(name), value(value){}
    void fix() {
        // Fix this->value (make this->value const)
    }
    void print() { std::cout << value << std::endl; }
};

我想在初始化后的某个时候对值变量进行“const-ify”

std::string name = "variance";
double var = 1.0;
Parameter<double> variance(name, var);
variance.print();
variance.fix();
variance.value = 2.3; // Not Allowed, throws error

是否可以这样做以及如何做到这一点?

【问题讨论】:

  • 可能不是你想要的,但你可以创建一个对象,用fix() 包装类型。删除所有默认赋值/移动运算符并重新定义它们以在修复值后引发错误。同样为此,您需要一个类,否则您可以直接更改值
  • 解决这个问题的方法是将变量设为私有,然后使用访问器方法获取和设置。 set 函数只允许你设置一次值,强制你不能再次设置值。

标签: c++ constants runtime


【解决方案1】:

如果您想维护相同的接口,并且您想避免通过访问器编组对value 的访问,那么您可以将“可修复”功能隔离在其自己的专用类型中,该类型隐式转换为@987654323/从@987654323 @:

template<typename T>
class fixable {
  bool fixed_ = false;
  T val_;

public:
  fixable() = default;
  fixable(T v) : val_(v) {}
  fixable(const fixable&) = default;
  fixable(fixable&&) = default;
  
  operator const T&() const { 
    return val_;
  }

  fixable& operator=(const T& v) {
    if(fixed_ ) {
      throw std::runtime_error("Fixable has been fixed");
    }

    val_ = v;
    return *this;
  }

  void fix() {
    fixed_ = true;
  }
};

然后,您将在Parameter 中将T 成员替换为fixable&lt;T&gt;

template<typename T>
struct Parameter {

    fixable<T> value;
    std::string name;

    Parameter(std::string name, T value) : name(name), value(value){}
    void fix() {
      value.fix();
    }
    void print() { std::cout << value << std::endl; }
};

您问题的主要功能可以保持原样。

【讨论】:

  • 您好,感谢您的回答,想知道如何将某些数据类型(如 Eigen::MatrixXd)用作可修复参数。例如,假设我有 Parameter&lt;Eigen::MatrixXd&gt; Z,我需要访问 (Eigen::MatrixXd) 方法 .array(),如 Z.array()。如果Z 现在是Fixable,我似乎不能这样做?
  • 你可以这样做:static_cast&lt;const Eigen::MatrixXd&amp;&gt;(param.value).array(); 但我承认这充其量是尴尬的......gcc.godbolt.org/z/cePsWMb1n
【解决方案2】:

你可以使用这样的东西: 类似于 abowe answer,但在 Parameter 结构中使用布尔值

template<typename T>
struct Parameter {
    Parameter(std::string name, T value) : name(name), value(value), bFixed(false) {}
    void fix() {
        bFixed = true;
    }
    void print() { std::cout << value << std::endl; }

    Parameter& operator=(const T& oValue)
    {
        if (bFixed)
        {
            throw std::runtime_error("Error fixed value..");
        }

        value = oValue;
        return *this;
    }

    std::string name;

private:
    bool bFixed;
    T value;
};

int main()
{
    std::string name = "variance";
    double var = 1.0;
    Parameter<double> variance(name, var);
    variance.print();
    variance.fix();
    variance = 2.3; // Not Allowed, throws error
}

【讨论】:

  • 尽管如此,没有什么能阻止某人写variance.value = 2.3。如果要采用这种方法,value必须设为私有。
【解决方案3】:

您不能将成员变量从 const 更改为 non-const。但是,您可以创建一个新对象,其中它是 const。例如:

template<typename T>
struct example {
    T value;

    example<T const> fix() && {
        return {value};
    }
};

int main(){
    auto x = example<int>{1};
    x.value = 4; // OK
    auto y = std::move(x).fix();
    y.value = 7; // error: assignment of read-only member
}

&amp;&amp; 的存在会强制使用 std::move,这表明不应再使用 x

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-11
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    相关资源
    最近更新 更多