简体   繁体   English

从Visual Studio 2010迁移到2012时出现C ++ 11问题

[英]C++11 issues when moving from Visual Studio 2010 to 2012

I'm trying to port my project from Visual Studio 2010 to Visual Studio 2012. In my code I have some file handling that looks like this: 我正在尝试将我的项目从Visual Studio 2010移植到Visual Studio 2012.在我的代码中,我有一些文件处理,如下所示:

auto fileDeleter = [](FILE* f) { fclose(f); };

unique_ptr<FILE, decltype(fileDeleter)> fMinute(
    fopen(minuteLogName.c_str(), "w"), fileDeleter);


unique_ptr<FILE, decltype(fileDeleter)> fIndividual(
    fopen(individualLogName.c_str(), "w"), fileDeleter);

if (!fMinute || !fIndividual) {
    throw Exceptions::IOException("One of the log files failed to open",
                                  __FUNCTION__);
}

This built with no issues in 2010, but in 2012 it fails on the conditional with: 这在2010年没有任何问题,但在2012年它失败了条件:

error C2678: binary '!' 错误C2678:二进制'!' : no operator found which takes a left-hand operand of type > 'std::unique_ptr<_Ty,_Dx>' (or there is no acceptable conversion) :没有找到哪个运算符采用类型>'std :: unique_ptr <_Ty,_Dx>'的左手操作数(或者没有可接受的转换)
... ...
could be 'built-in C++ operator!(bool)' 可能是'内置C ++运算符!(bool)'

The C++11 standard specifies that unique_ptr has a bool operator to allow you to do quick checks like I have above. C ++ 11标准指定unique_ptr有一个bool运算符 ,允许你像我上面那样进行快速检查。 Stranger yet, VS2012's unique_ptr definition has this very operator: 更奇怪的是,VS2012的unique_ptr定义有这样的运算符:

_OPERATOR_BOOL() const _NOEXCEPT
{   // test for non-null pointer
    return (this->_Myptr != pointer() ? _CONVERTIBLE_TO_TRUE : 0);
}

But I get that error upon compilation. 但是我在编译时遇到了这个错误。 Why? 为什么?

Yes, I could just be using ofstream instead, but that's besides the point. 是的,我可以只使用ofstream ,但这不仅仅是重点。

To build on what BigBoss said, C++11 requires that std::unique_ptr use explicit operator bool() noexcept , which solves the whole implicit conversion to bool problem. 为了构建BigBoss所说的,C ++ 11要求std::unique_ptr使用explicit operator bool() noexcept ,它解决了整个隐式转换为bool问题。 Except... VC2012 doesn't support explicit operators yet. 除了...... VC2012还不支持 explicit运算符。 Therefore, they have to use the safe-bool idiom . 因此,他们必须使用安全布尔的习语

While the safe-bool idiom is good, it can have flaws (which is why explicit operator bool() exists), depending on how you implement the idiom. 虽然安全bool成语很好,但它可能有缺陷(这就是explicit operator bool()存在的原因),这取决于你如何实现这个习语。 And you apparently ran across one of them in VC2012. 你显然在VC2012遇到过其中一个。 Reconfiguring your test, with !(fMinute && fIndividual) , should solve it. 使用!(fMinute && fIndividual)重新配置您的测试应该解决它。

But either way, it's a Visual Studio bug. 但无论哪种方式,它都是Visual Studio的错误。 Since the behavior changed, you should file a bug report even if you do manage to find a way around it. 由于行为发生了变化,即使您设法找到解决方法,也应该提交错误报告。

You can use if (!(fMinute && fIndividual) ) instead of if (!fMinute || !fIndividual) . 您可以使用if (!(fMinute && fIndividual) )而不是if (!fMinute || !fIndividual) C++ say that they are convertible to bool, but operator bool usually create problems, for example you may have a function that accept int , if your class have an operator bool then it is convertible to int and you can pass it to this function, but for example in our case unique_ptr never intended to be used as an int , so many developers never use operator bool directly but instead write an operator that can be used as a bool in conditional expressions but it is not actually bool! C ++说它们可以转换为bool,但是operator bool通常会产生问题,例如你可能有一个接受int的函数,如果你的类有一个operator bool然后它可以转换为int而你可以将它传递给这个函数,但是例如在我们的例子中, unique_ptr从不打算用作int ,所以许多开发人员从不直接使用operator bool ,而是编写一个可以在条件表达式中用作bool的运算符,但它实际上并不是bool!

struct bool_convertible {
    typedef void (*convertible_to_bool)();
    static void convertible_to_true();
    operator convertible_to_bool () const {
        return test() ? &convertible_to_true : nullptr;
    }
};

Using this technique I may have bool_convertible c; if( c ) {...} 使用这种技术我可能有bool_convertible c; if( c ) {...} bool_convertible c; if( c ) {...} but I can't have bool_convertible c; if( c ) {...}但我不能拥有

void test_int( int );
bool_convertible c;
test_int( c );

In the recent C++11 standard, std::unique_ptr has no operator! 在最近的C ++ 11标准中,std :: unique_ptr没有operator! defined, only the explicit conversion operator 定义,只显示转换运算符

explicit operator bool() const;

However, the built-in unary logical negation operator, ! 但是,内置的一元逻辑否定运算符, ! , contextually converts its argument to bool according to 5.3.1/9: ,根据5.3.1 / 9将其参数上下文转换为bool:

The operand of the logical negation operator ! 逻辑否定运算符的操作数! is contextually converted to bool (Clause 4); 在上下文中转换为bool (第4条); its value is true if the converted operand is false and false otherwise 如果转换的操作数为false,则其值为true,否则为false

Contextual conversion to bool will use an explicit conversion operator, if available. 如果可用,上下文转换为bool将使用显式转换运算符。 So, your code is actually expected to work under C++11 rules. 因此,您的代码实际上应该在C ++ 11规则下工作。 You should probably file a bug report to Microsoft. 您应该向Microsoft提交错误报告。 Whether they support explicit conversion operators or not should not matter. 它们是否支持显式转换运算符无关紧要。

As a workaround try this: 作为解决方法试试这个:

if (!fMinute.get() || !fIndividual.get()) {
    ....

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM