0

像申报储物柜时,

lock_guard Locker(mLocker);


我希望编译器检测 mLocker 是否是互斥锁。

为了实现这一点,我使用了概念要求并定义如下。

template <typename T>
concept is_mutex = requires
{
  std::is_same_v<T, std::recursive_mutex>;
};
template <class T> requires is_mutex<T> using expLock = std::lock_guard<T>;


如上所述,互斥锁针对类型 T 进行了验证,并且类型 T 的 std::lock_guard 通过使用关键字进行了别名。

但是当使用该别名(expLock)声明一个储物柜时。

std::recursive_mutex mutex_Lock;
expLock Locker(mutex_Lock); // error : No argument list for alias template expLock.


上面的代码会导致编译错误。

似乎 std::lock_guard 构造函数的显式关键字被忽略了,因为下面的代码将类型 T 强制为 std::lock_guard。

template <class T> requires is_mutex<T> using expLock = std::lock_guard<T>;
// CLASS TEMPLATE lock_guard
template <class _Mutex>
class _NODISCARD lock_guard { // class with destructor that unlocks a mutex
public:
    using mutex_type = _Mutex;

    explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock
        _MyMutex.lock();
    }

    ...

private:
    _Mutex& _MyMutex;
};


当然,如果在 alias(expLock) 中指定类型 T 如下所示,则不会出现编译错误。

std::recursive_mutex mutex_Lock;
expLock<std::recursive_mutex> Locker(mutex_Lock);


但我希望下面的代码能够在没有编译错误的情况下工作。

template <typename T>
concept is_mutex = requires
{
  std::is_same_v<T, std::recursive_mutex>;
};
template <class T> requires is_mutex<T> using expLock = std::lock_guard<T>;
std::recursive_mutex mutex_Lock;
expLock Locker(mutex_Lock); // error : No argument list for alias template expLock.


如何仅将互斥锁传递给 lock_guard 构造函数参数?

我应该定义一个像 std::lock_guard 这样的新 Locker 类吗?或者我需要修复别名吗?

也是这样还是有新的解决方案?



这个问题已经在下面的评论中得到了回答。

根据 cppreference,MSVC 在 19.27* 之后实现了 P1814,所以如果您的 MSVC 版本比 19.27* 新,您的代码将在使用 /std:c++latest 标志时编译。——康桓玮</p>

如果当前项目的 MSVC 是 19.27 或更高版本,则可以省略 using 关键字的模板参数列表。但是,如果您使用 Visual Studio 的 Intellisense,Intellisense 可能会显示错误消息。如果在 MSVC 19.27 或更高版本中弹出 using 关键字的模板参数列表错误消息,则该错误消息可能是由于 Intellisense 补丁不基于 MSVC 版本。除了 Intellisense 弹出的错误消息外,构建工作没有任何问题。- 정명준

4

1 回答 1

2

首先,您的概念is_mutex定义不正确。它只会检查 requires 子句中的有效性而不is_same_v评估它。您需要将其定义为:

template <typename T>
concept is_mutex = requires { requires std::is_same_v<T, std::recursive_mutex>; };

要不就:

template <typename T>
concept is_mutex = std::is_same_v<T, std::recursive_mutex>;

上面的代码会导致编译错误。

事实上,上面的代码在 C++20 中是格式良好的。我猜你正在使用 Clang,它目前没有为 Alias Templates 实现 Class Template Argument Deduction

于 2021-11-15T02:51:33.803 回答