gpt4 book ai didi

c++ - 有两个不同版本的箭头运算符?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:09:15 25 4
gpt4 key购买 nike

我有以下用于锁定对象的类:

#include <memory>

template <class Type, class Mutex>
class LockableObject {
public:
class UnlockedObject {
public:
UnlockedObject(Mutex &mutex, Type &object)
: mutex_(mutex), object_(object) {}
UnlockedObject(UnlockedObject &&other) = default;

// No copying allowed
UnlockedObject(const UnlockedObject &) = delete;
UnlockedObject &operator=(const UnlockedObject &) = delete;

~UnlockedObject() { mutex_.unlock(); }

Type *operator->() { return &object_; } // Version 1
// Type &operator->() { return object_; } // Version 2


private:
Mutex &mutex_;
Type &object_;
};

template <typename... Args>
LockableObject(Args &&... args) : object_(std::forward<Args>(args)...) {}

UnlockedObject Lock() {
mutex_.lock();
return UnlockedObject(mutex_, object_);
}

private:
Mutex mutex_;
Type object_;
};

我想按如下方式使用它来锁定和解锁对共享对象的访问。第二个示例利用了 -> 运算符多次应用自身的能力:

  // Example 1
{
LockableObject<std::string, std::mutex> locked_string;
auto unlocked_string = locked_string.Lock();
// This is what I want:
unlocked_string->size(); // works for version 1, breaks for version 2
}

// Example 2
{
LockableObject<std::unique_ptr<std::string>, std::mutex> locked_string(std::unique_ptr<std::string>(new std::string()));
auto unlocked_string = locked_string.Lock();
// This is what I want:
unlocked_string->size(); // works for version 2, breaks for Version 1

// Workaround
unlocked_string->get()->size(); // works for version 1, but is not nice
}

能否以某种方式更改类,使两个示例都使用 unlocked_string->size() 而不是使用 ->get() 的解决方法?可能是通过使用模板特化或类似的东西?

最佳答案

LockablePtrLockableValue类型。

LockableObject根据传入的类型有条件地选择上述哪一个。使用某种 SFINAE 或特征或类似的检测智能指针。

这个选择可以通过 using别名,或通过继承 using获取父构造函数。

namespace details {
template<template<class...>class, class, class...>
struct can_apply : std::false_type {};
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...> : std::true_type {};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z, void, Ts...>;

template<class T>
using star_r = decltype( *std::declval<T>() );
template<class T>
using is_ptr_like = can_apply< star_r, T >;

is_ptr_like是您可以一元取消引用的事物的特征。

假设您同时拥有 LockablePtr<T,M>LockableValue<T,M>写的。

template<class T, class M>
using Lockable =
typename std::conditional< is_ptr_like<T&>::value,
LockablePtr<T, M>,
LockableValue<T, M>
>::type;

template<class T, class M>
struct LockableObject:Lockable<T,M> {
using Lockable<T,M>::Lockable;
};

完成。

顺便说一句,您的存储选择

Type&

看起来很糟糕。

关于c++ - 有两个不同版本的箭头运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44461873/

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