2012-10-20 30 views
7

我想我的港口项目从Visual Studio 2010到Visual Studio 2012年在我的代码问题时,我有一些文件处理,看起来像这样:C++ 11个从Visual Studio 2010移动到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__); 
} 

此建有没有问题,2010年,但在2012年,在有条件的失败:

错误C2678:“!”二进制:没有找到操作符,该操作符需要类型>'std :: unique_ptr < _Ty,_Dx>'(或者没有可接受的转换)
...
可能是'内置的C++操作符! bool)'

C++ 11标准指定unique_ptr has a bool operator允许您像上面那样进行快速检查。但陌生人,VS2012的的unique_ptr定义有这个非常操作:

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

但是我在编译时得到这个错误。为什么?

是的,我可以使用ofstream来代替,但那不是重点。

+0

这似乎是通过使用lambda作为一个定制删除引起的。如果你使用别的东西,例如一个规则的函数对象,那么就没有问题了。 –

回答

6

要建立在什么BigBoss的说,C++ 11要求std::unique_ptr使用explicit operator bool() noexcept,解决了全隐式转换来弥补问题。除... VC2012不支持支持explicit运营商尚未。因此,他们必须使用safe-bool idiom

虽然safe-bool成语很好,但它可能有缺陷(这就是为什么explicit operator bool()存在),具体取决于您如何实现该习语。你显然在VC2012中遇到了其中一个。用!(fMinute && fIndividual)重新配置你的测试,应该可以解决它。

但无论如何,这是一个Visual Studio的错误。由于行为改变了,即使你设法找到一个方法,你也应该提交一个错误报告。

+0

VS2012也不支持noexcept – doctorlove

1

您可以使用if (!(fMinute && fIndividual))而不是if (!fMinute || !fIndividual)。 C++表示它们可以转换为bool,但operator bool通常会产生问题,例如,如果您的类有operator bool,那么它可以转换为int并且可以将它传递给此函数,但例如,您可能有一个接受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; 
    } 
}; 

使用这个技术我可以有bool_convertible c; if(c) {...}但我不能有

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

既不是'if(!(foo && bar))'也不是'if(foo)'工作。 –

+0

'std :: unique_ptr'的特化不*可以转换为'bool'。然而,它们可以通过使用'explicit'转换操作符转换为'bool'上下文*转换为'bool'。 –

+0

@LucDanton:技术上是真的,但这并没有改变,因为“!”是事物可以上下文转换为“布尔”的上下文之一。 –

1

在最近的C++ 11标准,标准::的unique_ptr没有定义的operator!,只有明确的转换操作符

explicit operator bool() const; 

然而,内置的一元逻辑否定操作,!,上下文转换其根据5.3对bool的论点。1/9:

逻辑非操作者!根据上下文转换为bool(第4章)的操作数;如果转换后的操作数为假,则其值为真,否则为假

将上下文转换为bool将使用显式转换运算符(如果可用)。所以,你的代码实际上预计在C++ 11规则下工作。你应该向微软提交一份错误报告。他们是否支持显式转换操作符都不重要。

作为解决办法试试这个:

if (!fMinute.get() || !fIndividual.get()) { 
    .... 
相关问题