0

为了支持没有explicit关键字的编译器(例如 MSVC 2012),我必须实现安全的 bool 习惯用法。应该可以检查 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()-based 实现一切正常。问题实际上在于基于“安全布尔”的实现中的模棱两可的可转换性。应该如何解决?

注意:考虑 bool 转换实现独立于其他指针转换实现。如果不可能,请告诉我如何在相关情况下实现它,例如,如果Convertible其他转换运算符之一返回非空值,则计算结果为真。

UPD:我相信有一种方法可以使一个隐式转换比其他所有转换都更可取。

4

2 回答 2

1

确定需要隐式转换为其他指针类型吗?如果你不需要它,问题就会消失。

如果您确实需要隐式转换为指针类型,那么问题似乎没有实际意义:您不需要转换为 bool,因为转换为指针也会产生一个可以进行真实测试的值(就像常规的原始指针一样)。

int*但是由于您对and都有运算符,因此您仍然会遇到模棱两可的转换double*。这部分可能需要重新设计,因为不清楚如何期望单个值可以隐式转换为多个不相关的指针类型。

于 2015-12-17T12:38:09.847 回答
0

其实也没有什么好的解决办法。我找到了一个部分满足我的要求并管理其他要求被削弱的。

根据http://en.cppreference.com/w/cpp/language/implicit_cast,隐式转换的集合和顺序如下:

1) 零或一标准转换序列

2) 零次或一次用户自定义转换

3) 零或一标准转换序列

由于问题中的两种类型的转换都是用户定义的,并且都允许进一步的标准转换,bool因此我决定将operator int*()operator double*()转换函数更改为其他函数,并且operator Ptr<int>()模板类的行为与原始指针相同。特别是它可以转换为 bool 但这并不重要,因为它是第二次用户转换,因此它是被禁止的。因此,唯一转换为存在(来自“安全布尔”实现)。operator Ptr<double>Ptr<T>bool

此解决方案的缺点是客户端代码需要更改接口或执行显式转换为原始指针。

于 2015-12-17T14:36:55.113 回答