安全布尔多次转换歧义
Safe bool multiple conversions ambiguity
为了支持没有explicit
关键字的编译器(例如MSVC 2012),我必须实现安全布尔习惯用法。对于bool,应该是可检查的类正在建模指向许多类的指针,因此它应该可以转换为这些指针。下面的代码说明了这个想法:
// Uncomment this line to change implementation to 'safe bool'
// #define _COMPILER_NO_EXPLICIT
#if !defined(_COMPILER_NO_EXPLICIT)
#define OPERATOR_BOOL_MYTYPE(...)
#define OPERATOR_BOOL_IMPLEMENTATION(...)
public:
explicit operator bool() const noexcept
{
return __VA_ARGS__;
}
#else
#define OPERATOR_BOOL_MYTYPE(...)
private:
void safe_bool() {};
typedef __VA_ARGS__ safe_bool_my_type_t;
typedef void (safe_bool_my_type_t::*safe_bool_t)()
#define OPERATOR_BOOL_IMPLEMENTATION(...)
public:
operator safe_bool_t() const noexcept
{
return __VA_ARGS__ ?
&safe_bool_my_type_t::safe_bool :
nullptr;
}
#endif
class Convertible
{
public:
operator int*() const
{ return nullptr; }
operator double*() const
{ return nullptr; }
OPERATOR_BOOL_MYTYPE(Convertible);
OPERATOR_BOOL_IMPLEMENTATION(false);
};
int main(void)
{
Convertible a;
if (a)
{
// this 'if' statement introduces compilation error
// in 'safe bool' implementation
}
return 0;
}
如果我们使用基于explicit operator bool()
的实现,一切都可以正常工作。问题实际上在于基于"安全布尔"的实现中不明确的可转换性。应该如何解决?
注意:考虑布尔转换实现独立于其他到指针的转换实现。如果不可能,请告诉我如何在依赖情况下实现它,例如,如果Convertible
评估为true,则当其他转换运算符之一返回非零值时。
UPD:我相信有一种方法可以使一个隐式转换比其他所有隐式转换更可取。
您是否确定需要隐式转换为其他指针类型?如果你不需要,问题就会消失。
如果你确实需要隐式转换为指针类型,那么这个问题似乎没有意义:你不需要转换为bool,因为转换为指针也会产生一个可以进行真值测试的值(就像普通的原始指针一样)。
但是,由于int*
和double*
都有运算符,因此仍然存在不明确的转换。这部分可能需要重新设计,因为尚不清楚如何将单个值隐式转换为多个不相关的指针类型。
实际上没有好的解决方案。我发现一个部分满足我的需求,并设法削弱了其他需求。
根据http://en.cppreference.com/w/cpp/language/implicit_cast隐式转换的集合和顺序如下:
1) 零或一个标准转换序列
2) 零或一个用户定义的转换
3) 零或一个标准转换序列
由于问题中的两种类型的转换都是用户定义的,并且都允许进一步标准转换为bool
,我决定将operator int*()
和operator double*()
转换函数更改为其他operator Ptr<int>()
和operator Ptr<double>
,其中Ptr<T>
是一个模板类,其行为与原始指针相同。特别是它可以转换为bool,但这并不重要,因为这是第二次用户转换,因此它是被禁止的。因此,存在到bool
的唯一转换(来自"安全布尔"实现)。
此解决方案的缺点是需要客户端代码来更改接口或执行对原始指针的显式强制转换。
- 为什么下面带有非常量转换函数的代码没有歧义?
- 如何在模板化转换运算符中消除此构造的歧义?
- 函数调用歧义(用户定义的转换和 Derived2Base 指针转换)
- C++中的重载歧义,用于自动将对象转换为"printable"格式
- 资格转换的歧义
- 在隐式转换后的智能指针上删除函数调用中的歧义
- 解决隐藏歧义的不明确用户定义转换
- 为什么我总是必须除以 49 才能得到二进制转换器 + cout 歧义的正确答案?
- 转换运算符重载歧义,编译器不同
- 如何解决转换构造函数和普通构造函数之间的歧义
- 转换 - 错误 E2015,AnsiString(char) 和 AnsiString(short) 之间的歧义
- 调用函数的歧义.隐式转换
- C++11:在按值传递参数初始化时转换构造函数和转换函数之间的歧义
- g++和clang++-删除由重载转换运算符歧义获取的指针
- 安全布尔多次转换歧义
- 当目标类有多个构造函数时,消除强制转换操作符的歧义
- 在将派生类指针转换为基类时,基类有歧义
- 歧义调用(从char*到lambda与std::string的转换)
- 运算符=与转换运算符结合时的歧义
- 转换运算符重载 - 函数歧义