在 if 语句中声明类变量

3

C++的接受:

if(int a=1)
{
    //...
}

为了学习目的,我编写了一个简单的锁机制类:

class SimpleLock
{
public:
    class Token
    {
    public:
        friend class SimpleLock;
        Token(SimpleLock & lock) : lock(lock), locked(!lock.locked.exchange(true)) { }
        ~Token() { if(locked) lock.locked.store(false); }
        operator bool() const { return locked; }

    private:
        SimpleLock & lock;
        const bool locked;
    };

    SimpleLock() : locked(false) { }

private:
    std::atomic_bool locked;
};

允许我做以下事情:
SimpleLock::Token t(lock);

if(t) //Token has an operator bool() overload
{
    //...
}

以下代码为什么无法编译?
if(SimpleLock::Token t(lock))
{
    //...
}

编译器错误:

't'之前需要主表达式

在线代码链接:http://goo.gl/Knrmw7


1
以下代码为什么无法编译通过?通常来说,编译器会提示你原因。请将错误信息复制到你的问题中。 - eerorika
2
编译器说了什么? - Bo Persson
3
如果这个问题有一个 [mcve],我可能会点赞,但我不想编写代码来找出这个问题是否有效。 - Baum mit Augen
1
@galinette 差不多了,给你点赞。为了教育目的:一个真正的MCVE,包括错误信息。 - Baum mit Augen
显示剩余5条评论
2个回答

10

无法编译,因为在if条件中不允许这种初始化方式。这只是语法形式不被标准认可的缘故。

你可以使用复制初始化形式或花括号初始化列表:

if(SimpleLock::Token t = SimpleLock::Token(lock))
{
    //...
}

if(SimpleLock::Token t{lock})
{
    //...
}

这在《C++11标准草案(N3337)》的[stmt.select]/1中有明确规定:
条件可以是以下任意一种形式:
- 表达式 - 属性说明符序列可选 声明说明符序列 声明符 = 初始化列表 - 属性说明符序列可选 声明说明符序列 声明符 列表初始化式

3

来自http://zh.cppreference.com/w/cpp/language/if

语法为if ( condition )

其中,condition 可以是以下之一:

  • 可转换为 bool 的表达式
  • 使用花括号或等号初始化器声明的单个非数组变量。

这里我们使用第二个条件,因此

你必须使用带有=的语法:

if (SimpleLock::Token t = SimpleLock::Token(lock))
{
    //...
}

演示

或者使用{}来构建对象(而不是()

if (SimpleLock::Token t{lock})
{
    //...
}

演示


1
可能是因为复制运算符返回的是某些东西,而非构造函数。 - galinette
谢谢,我删掉了我的回答。这看起来还不错。顺便说一下,在C++11中,似乎if(SimpleLock::Token t {lock})是可行的。但我无法看出为什么这会导致某些棘手的解析问题... - vsoftco
1
@galinette:使用复制/移动构造函数,而不是赋值。 - Jarod42
1
我会说t(lock)由于解析问题(例如最棘手的解析)而不被接受。 - Jarod42
@galinette 跟进问题:https://dev59.com/7pTfa4cB1Zd3GeqPLxit。我认为这里不应该有任何令人烦恼的解析,尽管从错误信息看起来似乎有,但不知道原因。 - vsoftco
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接