可以将 class 对象创建为仅左值吗?

Can a class object be created as an lvalue-only?

std::lock_guard(及其相关)的一个众所周知的问题是,当仅创建一个临时对象时,它无法按预期方式工作。

例如:

std::mutex mtx;

std::lock_guard<std::mutex> {mtx} // temporary object, does not lock the entire scope

std::lock_guard<std::mutex> lck{mtx} // correct

我尝试使用引用限定符来创建一个替代品,以防止创建临时对象(在编译时)。以下代码是徒劳的尝试:

#include <mutex>

template<typename T>
struct my_lock {
    T &mtx;
    my_lock(T &t) : mtx{t} { lock(); }
    ~my_lock() { unlock(); }

    void lock() & { mtx.lock(); };
    void unlock() & { mtx.unlock(); };
};


std::mutex mtx;

int main()
{
    my_lock<std::mutex> {mtx}; // A 

    my_lock<std::mutex lck{mtx}; // B
}

这行不通,所以问题变成:

是否可以以编译器拒绝 A 并接受 B 的方式编写 class?

如果可以使用c++17,则可以使用具有工厂功能的[[nodiscard]]属性。


class [[nodiscard]] my_lock{
   my_lock()=default;
   friend my_lock lock();
};
[[nodiscard]] my_lock lock(){return {};}

int main(){
    { lock(); } //warning for discard return value
    { auto l = lock();}
}

让我重新解释你的问题,而不是:

Is it possible to write the class in such a way that the compiler rejects A and accepts B ?

我要把它读成

Is it possible for my compiler to reject A and accept B?

是的,这取决于编译器,无需您自己编写 类。我对 clang 非常熟悉,但是,类似的检查将存在于其他编译器或静态分析器中。

对于 clang,-Wunused-value -Werror 就可以了。第一个激活警告,第二个将其提升为错误。

就我个人而言,我赞成启用所有警告并明确禁用那些您有理由不遵守的警告,包括说明原因的文档。