如何避免在易失性类中重复方法

Pat*_*ght 2 c++ volatile member-functions explicit-object-parameter

假设我有以下非常简单的类:

class A
{
public:
    static constexpr A make() { return A{}; }

    constexpr A() : _v(0) {}

    constexpr A& setV(int v) { _v = v; return *this; }

private:
    int _v;
};
Run Code Online (Sandbox Code Playgroud)

如果我尝试按如下方式使用它:

int main()
{
    volatile A a1;
    a1.setV(10);

    //OR

    //The optimizer will optimize this chain of constexpr calls into a single "store" instruction
    a1 = A::make().setV(10); //More chaining here

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该代码将无法编译。

我理解为什么这是真的,基于:定义易失性类对象

我知道解决方案是添加一个额外的方法,如下所示:

class A
{
public:
    constexpr A() : _v(0) {}

    volatile A& setV(int v) volatile { _v = v; return *this; }
    constepxr A& setV(int v) { _v = v; return *this; }

private:
    int _v;
};
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我知道如果不使用它,返回易失性引用会发出警告。

我的问题是,在这种情况下有什么方法可以避免代码重复吗?的两种实现始终setV是相同。因此,如果我添加/更改更多方法,我必须维护它们,如果它们不是那么微不足道,这可能会变得混乱。唯一的区别是类型限定符之一......

由于评论中提到了这一点,我想我会注意到我在这里需要易失性,因为我试图最终在嵌入式系统上实现硬件外设寄存器访问的“类覆盖”。

Com*_*sMS 7

在 C++23 中,您可以使用显式对象参数(也称为推导 this)来实现此目的:

class A
{
public:
    A() : _v(0) {}
    template <class Self>
    constexpr auto&& setV(this Self&& self, int v) {
        self._v = v; return self;
    }
private:
    int _v;
};
Run Code Online (Sandbox Code Playgroud)

不幸的是,截至撰写本文时,唯一支持此功能的编译器是最新版本的 Microsoft Visual C++。