gpt4 book ai didi

c++ - 如何让编译器更喜欢 C++ 中的 const 方法重载?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:18:03 24 4
gpt4 key购买 nike

我有一个具有 const 和非 const 重载的类的 C++ 成员函数。

Class Example {
public:
int const & Access() const;
int & Access();

[...]
};

我希望 const 版本成为首选,因为在我的代码中性能要好得多,非 const 版本会导致创建底层共享对象的拷贝以允许修改。

现在,如果我的调用者有一个非常量 Example 对象,即使结果 int 没有被修改,也会使用非常量 Access() 方法。

Example example;

if ( modify ) {
example.Access() = 23; // Need to perform expensive copy here.
} else {
cout << example.Access(); // No need to copy, read-only access.
}

有没有一种方法,比如区分返回值的左值和右值使用,也许使用模板的完美转发,在 C++17 中创建一个类似的机制,允许调用者有一个编译器只使用的语法如果修改了返回值,则为非 const 版本?

我需要它的另一个例子是 operator -> () 我有一个 const 和非 const 版本的运算符.当调用 const 的方法时,我希望编译器更喜欢 operator -> ()const 版本。

Class Shared {
public:
int Read() const;
void Write(int value);

[...]
};

template <typename BaseClass>
class Callback {
public:
BaseClass const * operator -> () const; // No tracking needed, read-only access.
BaseClass * operator -> (); // Track possible modification.

[...]
};

typedef Callback<Shared> SharedHandle;

Shared shared;
SharedHandle sharedHandle(&shared);

if ( modify ) {
sharedHandle->write(23);
} else {
cout << sharedHandle->Read();
}

最佳答案

最简单的方法是创建一个 CAccess 成员(类似于 stdlib 容器上的 cbegin):

class Example {
public:
int const & Access() const;
int & Access();
int const & CAccess() const { return Access(); }
// No non-const CAccess, so always calls `int const& Access() const`
};

这有一个缺点,如果你不修改它,你需要记住调用 CAccess

你也可以返回一个代理:

class Example;

class AccessProxy {
Example& e;
explicit AccessProxy(Example& e_) noexcept : e(e_) {}
friend class Example;
public:
operator int const&() const;
int& operator=(int) const;
};

class Example {
public:
int const & Access() const;
AccessProxy Access() {
return { *this };
}
private:
int & ActuallyAccess();
friend class AccessProxy;
};

inline AccessProxy::operator int const&() const {
return e.Access();
}

inline int& AccessProxy::operator=(int v) const {
int& value = e.ActuallyAccess();
value = v;
return value;
};

但这里的缺点是类型不再是int&,这可能会导致一些问题,只有operator=被重载。

第二个可以很容易地应用于 operator,通过创建一个模板类,如下所示:

#include <utility>

template<class T, class Class, T&(Class::* GetMutable)(), T const&(Class::* GetImmutable)() const>
class AccessProxy {
Class& e;
T& getMutable() const {
return (e.*GetMutable)();
}
const T& getImmutable() const {
return (e.*GetImmutable)();
}
public:
explicit AccessProxy(Class& e_) noexcept : e(e_) {}
operator T const&() const {
return getImmutable();
}
template<class U>
decltype(auto) operator=(U&& arg) const {
return (getMutable() = std::forward<U>(arg));
}
};

class Example {
public:
int const & Access() const;
auto Access() {
return AccessProxy<int, Example, &Example::ActuallyAccess, &Example::Access>{ *this };
}
private:
int & ActuallyAccess();
};

(虽然 AccessProxy::operator-> 也需要定义)

并且第一种方法不适用于 operator 成员(除非您愿意将 sharedHandle->read() 更改为 sharedHandle.CGet ().read())

关于c++ - 如何让编译器更喜欢 C++ 中的 const 方法重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57564832/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com