将变量转换为布尔类型

3

如何在C++Builder 10中将Variant转换为bool?

在旧的bcc32编译器中,我使用以下代码检查某些通用TComponent是否启用:

if ((bool)GetPropValue(c, "Enabled", false))
    do_something();

然而,在升级到C++Builder 10并启用新的基于Clang的编译器后,我遇到了以下错误:

[CLANG Error] VclHelpers.cpp(1375): ambiguous conversion for C-style cast from 'System::Variant' to 'bool'

完整的编译器消息表明,Variant的36个转换运算符被认为是合法的候选项:operator double()operator wchar_t*等。

我之前没有使用过C++Builder,但是一个选项可能是转换为int类型? - user2672165
@user2672165 - 是的,那似乎可以工作,但看起来不太优雅。 - Josh Kelley
@JoshKelley:你为什么还要费心使用RTTI呢?TControl::Enabled属性是公共的,所以你可以这样做:if (c->Enabled) ...。如果你要使用RTTI,那么你可以考虑使用TRttiProperty::GetValue()代替GetPropValue(),因为TRttiProperty::GetValue()返回一个TValue,它有一个AsBoolean()方法。TRttiContext ctx; if (ctx.GetType(c->ClassType())->GetProperty("Enabled")->GetValue(c).AsBoolean()) ... - Remy Lebeau
@JoshKelley:如果你要使用GetPropValue(),那么至少可以摆脱显式类型转换。让编译器为你确定调用哪个转换运算符:bool bEnabled = GetPropValue(c, "Enabled", false); if (bEnabled) ...。否则,直接调用所需的运算符而不是使用类型转换:if (GetPropValue(c, "Enabled", false).operator bool()) ... - Remy Lebeau
@JoshKelley:如果你有一个 TComponent*,并且想要检查 TControl::Enabled 属性,只需使用 dynamic_cast 进行类型转换为 TControl*(以防 TComponent* 指向的不是 TControl 的后代),例如:TControl *ctrl = dynamic_cast<TControl*>(c); if ((ctrl) && (ctrl->Enabled)) ... - Remy Lebeau
显示剩余3条评论
1个回答

4
问题在于Variant提供了太多的转换运算符。特别是下面这些运算符会使得转换为布尔值变得不清晰:
__fastcall operator bool() const;
__fastcall operator signed char*();
__fastcall operator unsigned char*();
// etc. - Variant has similar operators for short, int, long, float, double...
// It calls these "by ref" conversions.

据我理解,在非const重载和const重载之间,通常优先选择非const重载。但是,在存在>1个非const可转换为bool指针转换以及一个const bool转换的情况下,该转换是有歧义的。

很可能Variant的转换设计方式存在问题,导致它们无法在没有歧义的情况下使用。但是,在@user2672165和@Remy Lebeau的评论的帮助下,有几种解决方法:

// Convert to int instead of bool.
if ((int)GetPropValue(c, "Enabled", false)) {}

// Make the Variant const, to avoid the ambiguous non-const conversions.
if (const_cast<const Variant>(GetPropValue(c, "Enabled", false))) {}

// Explicitly invoke the desired conversion operator.
if (GetPropValue(CheckBox1, "Enabled", false).operator bool()) {}

// Use TRttiProperty instead of Variant.
RttiContext ctx;
if (ctx.GetType(c->ClassType())->GetProperty("Enabled")->GetValue(c).AsBoolean()) {}

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