从 Visual Studio 2010 迁移到 2012 时的 C++11 问题
Posted
技术标签:
【中文标题】从 Visual Studio 2010 迁移到 2012 时的 C++11 问题【英文标题】:C++11 issues when moving from Visual Studio 2010 to 2012 【发布时间】:2012-10-20 22:42:50 【问题描述】:我正在尝试将我的项目从 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__);
这在 2010 年没有问题,但在 2012 年它在条件下失败了:
错误 C2678:二进制“!” : 未找到采用左手操作数类型 > 'std::unique_ptr<_ty>' 的运算符(或没有可接受的转换) ... 可能是“内置 C++ 运算符!(布尔)”
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
,但这不是重点。
【问题讨论】:
这似乎是由于使用 lambda 作为自定义删除器造成的。如果您使用其他东西,例如一个普通的函数对象,那么就没有问题了。 【参考方案1】:为了建立在 BigBoss 所说的基础上,C++11 要求 std::unique_ptr
使用 explicit operator bool() noexcept
,这解决了整个隐式转换为 bool 的问题。除了... VC2012 还不支持 explicit
运算符。因此,他们必须使用safe-bool idiom。
虽然 safe-bool 成语很好,但它可能存在缺陷(这就是存在 explicit operator bool()
的原因),具体取决于您如何实现该成语。您显然在 VC2012 中遇到了其中之一。使用!(fMinute && fIndividual)
重新配置您的测试应该可以解决它。
但无论哪种方式,这都是 Visual Studio 的错误。由于行为发生了变化,即使您设法找到解决方法,您也应该提交错误报告。
【讨论】:
VS2012也不支持noexcept【参考方案2】:您可以使用if (!(fMinute && fIndividual) )
代替if (!fMinute || !fIndividual)
。 C++ 说它们可以转换为 bool,但 operator bool
通常会产生问题,例如,您可能有一个接受 int
的函数,如果您的类有一个 operator bool
,那么它可以转换为 int,您可以将其传递给这个函数,但例如在我们的例子中,unique_ptr
从未打算用作int
,因此许多开发人员从不直接使用operator 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 );
【讨论】:
std::unique_ptr
的特化不能转换为bool
。但是,它们可以上下文通过使用explicit
转换运算符转换为bool
到bool
。
@LucDanton:技术上是正确的,但这并没有改变,因为“!”是可以在上下文中转换为 bool
的上下文之一。
@NicolBolas 这不会让这个答案变得更有用。【参考方案3】:
在最近的 C++11 标准中,std::unique_ptr 没有定义operator!
,只有显式转换运算符
explicit operator bool() const;
但是,内置的一元逻辑否定运算符 !
根据 5.3.1/9 上下文将其参数转换为 bool:
逻辑否定运算符
!
的操作数根据上下文转换为bool
(第4 条);如果转换后的操作数为假,则其值为真,否则为假
到布尔的上下文转换将使用显式转换运算符(如果可用)。因此,您的代码实际上应该在 C++11 规则下工作。您可能应该向 Microsoft 提交错误报告。它们是否支持显式转换运算符无关紧要。
作为一种解决方法,试试这个:
if (!fMinute.get() || !fIndividual.get())
....
【讨论】:
以上是关于从 Visual Studio 2010 迁移到 2012 时的 C++11 问题的主要内容,如果未能解决你的问题,请参考以下文章
ASP.Net - 从 Visual Studio 2003 过渡到 Visual Studio 2010
从 Visual Studio 2005 迁移到 2008 和 .NET 2.0
迁移的 Visual Studio 项目未找到 NuGet 包