&引用;美化;宏 看萨特在C++中谈论atomics,我瞥见他的想法是一个易于使用的锁/解锁机制,它可能或可能不在未来的语言标准中。

&引用;美化;宏 看萨特在C++中谈论atomics,我瞥见他的想法是一个易于使用的锁/解锁机制,它可能或可能不在未来的语言标准中。,c++,c++11,macros,C++,C++11,Macros,其机制如下所示: atomic{ // code here } 我不想等待未来的标准,我尝试自己实现这个标准,我想到的是: #define CONCAT_IMPL(A, B) A ## B #define CONCAT(A, B) CONCAT_IMPL(A, B) # define atomic(a) { \ static_assert(std::is_same<decltype(a), std::mutex>::value,"Argument must be of type

其机制如下所示:

atomic{
// code here
}
我不想等待未来的标准,我尝试自己实现这个标准,我想到的是:

#define CONCAT_IMPL(A, B) A ## B
#define CONCAT(A, B) CONCAT_IMPL(A, B)

# define atomic(a) { \
static_assert(std::is_same<decltype(a), std::mutex>::value,"Argument must be of type std::mutex !");\
struct CONCAT(atomic_impl_, __LINE__)\
{\
std::function<void()> func;\
std::mutex* impl;\
CONCAT(atomic_impl_, __LINE__)(std::mutex& b)\
{ \
    impl = &b;\
    impl->lock();\
}\
CONCAT(~atomic_impl_, __LINE__)()\
{ \
    func();\
    impl->unlock(); \
}\
} CONCAT(atomic_impl_var_, __LINE__)(a);\
CONCAT(atomic_impl_var_, __LINE__).func = [&]()
问题显然是〈强〉我想删除它


这有可能吗?

使用。如果你想包含一个宏,我想你可以,它会让你省去选择一个变量名的麻烦,而且它会避免意外地创建一个临时变量而不是一个变量的打字错误。

你可以通过在
If
语句中定义变量来做到这一点

template <typename M>
struct atomic_guard_ {
  explicit atomic_guard_(M& m) : lock(m) {}
  atomic_guard_(M const&) =delete; // Since we unfortunately have to use uniform
  atomic_guard_(M&&) =delete;      // initialization, make it at least a little safe
  operator bool() const { return false; }
  std::lock_guard<M> lock;
};

#define atomic(m) \
  if (atomic_guard_<std::decay<decltype(m)>::type> _{m}) {} else

int main()
{
  std::mutex m;
  atomic(m) {
    std::cout << "a\n";
  }

  atomic(m) // this works too, but I think this is ok
    std::cout << "b\n";
}
模板
结构原子保护{
显式原子保护(M&M):锁(M){}
原子_-guard_um(const&)=delete;//因为我们不得不使用统一的
原子保护(M&&)=删除;//初始化,使其至少有一点安全
运算符bool()常量{return false;}
标准:锁和防护锁;
};
#定义原子(m)\
if(原子{m}){else
int main()
{
std::互斥m;
原子(m){

std::cout更简单的版本将使用
for
std::unique_lock

#include <iostream>
#include <type_traits>
#include <mutex>

#define atomic(a) \
  for(auto lock=std::unique_lock<std::decay<decltype(a)>::type>(a); lock; lock.unlock())

int main()
{
  std::mutex m;
  atomic(m) {
    std::cout << "Hello, world!" << std::endl;
  }
}
#包括
#包括
#包括
#定义原子(a)\
对于(auto lock=std::unique_lock(a);lock;lock.unlock())
int main()
{
std::互斥m;
原子(m){

std::cout临时变量的生存期不是与变量的生存期相同吗?+1,不需要复杂的解决方案来解决已在standard@James:打开一个作用域,创建一个命名的
锁护
(不是临时的!),当作用域退出时,它将释放锁):
{std::lock\u-guard l(m);…}
而不是问题中的
原子(m){…}
。@DavidRodríguez dribeas我想知道它是否具有与此相同的效果:
{std::lock_guard(m);…}
,但它没有,所以没关系。似乎你没有足够地清理代码…什么是
func
?它初始化在哪里?@DavidRodríguez dribeas:宏的最后一行我猜
开始原子(mut)…结束原子()
可能足够优雅。我认为您不会找到更好的解决方案,您将永远需要
};
:要么是程序员编写的,要么是程序员编写的宏编写的。@user1233963:哎哟……这个宏有太多问题了,我不知道从哪里开始……它是不对称的。除了锁定的成本之外,您还添加了一个动态分配(
std::function
存储lambda)…可能比
lock\u guard
(情人眼里出西施)好一点,但代价是什么?我更喜欢一个内部实例化了作用域锁的人工作用域。这是一种经过验证的模式,其他开发人员都很熟悉,不需要使用“宏作为代码”。这是不正确的…
if(condition)atomic(m){本不会想到这一点!绝对漂亮!我知道人们讨厌宏,但这是一个很好的方法将RAII对象“注入”到用户的块中。尽管对于这种特殊用途,直接使用
lock\u guard
可能更好,因为你不会完全得到(假定的)当然,David Rodríguez关于使用
if(…);else
需要发生。@MichaelBurr:我不讨厌宏,我只是发现它很容易出错。证据是答案中的原始代码在某些用例中失败了。一般来说,将RAII对象注入用户块的问题是通过在用户块中创建RAII对象来解决的。很少有情况下戴维德罗·德里格斯·德里比亚斯:我同意。我认为它在这里没有什么用处。但我仍然认为它很聪明。我可以有两种观点。
#include <iostream>
#include <type_traits>
#include <mutex>

#define atomic(a) \
  for(auto lock=std::unique_lock<std::decay<decltype(a)>::type>(a); lock; lock.unlock())

int main()
{
  std::mutex m;
  atomic(m) {
    std::cout << "Hello, world!" << std::endl;
  }
}