Wil*_*mKF 5 c++ const lazy-initialization perfect-forwarding c++17
我有一个带有a const和非const重载的类的C ++成员函数。
Class Example {
public:
int const & Access() const;
int & Access();
[...]
};
Run Code Online (Sandbox Code Playgroud)
我希望首选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.
}
Run Code Online (Sandbox Code Playgroud)
有没有一种方法,例如区分返回值的左值和右值使用,也许使用带有模板的完美转发,以在C ++ 17中创建类似的机制,从而允许调用者拥有一种语法,而编译器仅使用非语法。 const版本是否修改了返回值?
我需要这样做的另一个示例是operator -> ()我有一个const和非const版本的运算符。当调用方法时,const我希望编译器更喜欢的const版本operator -> ()。
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();
}
Run Code Online (Sandbox Code Playgroud)
最简单的方法是成为一个CAccess成员(就像cbegin在stdlib容器上一样):
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`
};
Run Code Online (Sandbox Code Playgroud)
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;
};
Run Code Online (Sandbox Code Playgroud)
但是这里的缺点是类型不再是int&,这可能会导致一些问题,并且只会operator=被重载。
operator通过制作一个模板类,第二个可以很容易地应用于s:
#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();
};
Run Code Online (Sandbox Code Playgroud)
(尽管AccessProxy::operator->也需要定义)
并且第一种方法对operator成员不起作用(除非您愿意更改sharedHandle->read()为sharedHandle.CGet().read())
| 归档时间: |
|
| 查看次数: |
144 次 |
| 最近记录: |