0

When declare locker like,

lock_guard Locker(mLocker);


I want the compiler to detect if an mLocker is a mutex.

To implement this, I used concept requires and defined as below.

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>;


As above, the mutex was verified for type T, and std::lock_guard for type T was aliased through using keyword.

But when declaring a locker with that alias(expLock).

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


Above code causes a compile error.

It seems that the explicit keyword of the std::lock_guard constructor was ignored because the code below forced type T to 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;
};


Of course, if type T is specified in the alias(expLock) as shown below, no compilation error occurs.

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


But I want the code below to work without compile errors.

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.


How to pass only mutex to lock_guard constructor parameter?

Should I define a new Locker class like std::lock_guard? or Do I need to fix the alias?

Is that too or is there a new solution?



This question has been answered in the comments below.

According to cppreference, MSVC implemented P1814 after 19.27*, so if your MSVC version is newer than 19.27*, your code will compile when use the /std:c++latest flag. – 康桓瑋

If the MSVC of the current project is version 19.27 or later, you can omit the template argument list for the using keyword. However, if you are using Visual Studio's Intellisense, Intellisense may display an error message. If a template argument list error message for the using keyword is popped up in MSVC 19.27 or later, This error message may be caused by the Intellisense patch not based on the MSVC version. Apart from the error message that Intellisense pops up, the build works without any problem. - 정명준

정명준
  • 5
  • 3

1 Answers1

2

First, Your concept of is_mutex is incorrectly defined. It will only check the validity of is_same_v in the requires clause without evaluating it. You need to define it as:

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

Or just:

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

Above code causes a compile error.

In fact, the above code is well-formed in C++20. I guess you are using Clang, which currently does not implement Class Template Argument Deduction for Alias Templates.

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
  • The part where the error occurred was not the "concept alias" part. The point of this question is that I wanted to declare Locker without requiring Type T because the compiler required an argument list for type T when I declared Locker using that alias (expLock). The solution "make_lock_guard" you suggested seems to be an impressive way to solve what I intended. But isn't the "return std::lock_guard(mutex_lock);" part locking only within the "make_lock_guard" block? – 정명준 Nov 15 '21 at 03:37
  • @정명준. When you use the alias to declare `Locker`, the compiler does *not* require you to specify `T` explicitly. The reason you encounter this problem is that your compiler does not implement this C++20 feature. That solution is my negligence, there seems to be no simple solution before the compiler implements [P1814](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1814r0.html). – 康桓瑋 Nov 15 '21 at 03:47
  • I didn't post "the current compiler language standard is c++20" in this question. Currently the compiler uses visual studio and the language standard is c++20. Are you saying that if the compiler supports c++20, that alias is fine? – 정명준 Nov 15 '21 at 03:54
  • According to [cppreference](https://en.cppreference.com/w/cpp/20), MSVC implemented P1814 after 19.27*, so if your MSVC version is newer than 19.27*, your code will compile when use the `/std:c++latest` flag. – 康桓瑋 Nov 15 '21 at 03:59
  • First of all, thank you for your comment. Unfortunately, however, the MSVC version was 19.29 and used the /std:c++latest flag, but the compiler still requires an argument list for Type T when declaring a Locker with that alias (expLock). I'll look into this a bit more and leave a comment again. – 정명준 Nov 15 '21 at 04:44
  • haha... It seems that there are no compile errors when solution building... But Intellisense of Visual Studio shows an error indication. The intention of this question was to cause an error by the compiler's Intellisense if a user passes an argument other than mutex to the constructor when declaring a locker through alias(expLock). – 정명준 Nov 15 '21 at 05:03