const-correctness和安全bool成语

时间:2011-08-11 15:00:45

标签: c++ const member-function-pointers const-correctness safe-bool-idiom

我还有另外一个与安全布尔成语有关的问题:

typedef void (Testable::*bool_type)() const;             // const necessary?
void this_type_does_not_support_comparisons() const {}   // const necessary?

operator bool_type() const
{
    return ok_ ? &Testable::this_type_does_not_support_comparisons : 0;
}

为什么bool_type(typedef)和this_type_does_not_support_comparisonsconst? 无论如何,没有人应该通过返回指针实际调用成员函数,对吗? 这里需要const吗? operator bool_type(成员函数)是否会违反const-correctness?

2 个答案:

答案 0 :(得分:5)

“安全bool成语”是“我想要一辆既是跑车又是拖拉机,也许是一艘船”的问题的技术答案。实际答案不是技术答案......

那就是说,它解决的问题只是给出一个可转换为bool的结果而不是其他任何东西的结果(否则该类的实例可以作为实际参数传递,例如形式参数是int,说)。数据指针可以转换为void*。函数指针不是,至少在C ++标准中是正确的(Posix是其他东西,也是练习)。

使用成员函数指针防止意外调用该函数,给定来自安全bool操作符的指针。 const稍微限制了它,但是如果命运让某人走上了制造最大数量的愚蠢错误的道路,那么这个人可能仍会设法调用无操作功能。而不是const 我认为我只是让它有一个私有类型的参数,其他代码不能提供这样的参数,然后它不必是一个愚蠢的成员函数类型了。

可以这样:

#include <stdio.h>

class Foo
{
private:
    enum PrivateArg {};
    typedef void (*SafeBool)( PrivateArg );
    static void safeTrue( PrivateArg ) {}

    bool    state_;

public:
    Foo( bool state ): state_( state ) {}

    operator SafeBool () const
    { return (state_? &safeTrue : 0); }
};

int main()
{
    if( Foo( true ) ) { printf( "true\n" ); }
    if( Foo( false ) ) { printf( "false\n" ); } // No output.

    //int const x1 = Foo( false );        // No compilado!
    //void* const x2 = Foo( false );      // No compilado!
}

当然,实际的答案是这样的:

#include <stdio.h>

class Foo
{
private:
    bool    isEmpty_;

public:
    Foo( bool asInitiallyEmpty )
        : isEmpty_( asInitiallyEmpty )
    {}

    bool isEmpty() const { return isEmpty_; }
};

int main()
{
    if( Foo( true ).isEmpty() ) { printf( "true\n" ); }
    if( Foo( false ).isEmpty() ) { printf( "false\n" ); } // No output.

    //bool const x0 = Foo( false );       // No compilado!
    //int const x1 = Foo( false );        // No compilado!
    //void* const x2 = Foo( false );      // No compilado!
}

摘要wrt。提问:

  • 为什么bool_type(typedef)和this_type_does_not_support_comparisons是const?

有人不太明白他们编码的是什么。或者也许他们打算限制通话的能力,一点点。但是,这非常徒劳无功。

  • 无论如何,没有人应该通过返回指针实际调用成员函数,对吗?

右。

  • 这里需要const吗?

没有

  • 运算符bool_type(成员函数)是否会违反const-correctness?

没有

干杯&amp;第h。,

答案 1 :(得分:1)

  

8.3.5 / cv-qualifier-seq只能是函数类型的一部分   非静态成员函数,指针所指向的函数类型   成员引用,或函数typedef的顶级函数类型   宣言。 cv-qualifier-seq在函数声明符中的作用   与在函数顶部添加cv-qualification不同   类型,即它不会创建一个cv限定的函数类型。

如果我读得正确,你可以在const成员函数中返回指向非const成员的指针。您将无法使用非const对象调用它。

禁止通话的方法是:

private:
    struct private_ 
    {
        void this_type_does_not_support_comparisons() {}
    };

public:
    typedef void (private_::*bool_type)() const;

    operator bool_type() const
    {
        return ok_ ? &private_::this_type_does_not_support_comparisons : 0;
    }

仍然可以比较指向成员函数的指针是否相等。您必须为operator==类型编写operator!=Testable::bool_type来触发错误。使用安全bool习语的CRTP形式更容易,因为这些操作符成为模板,因此可能有错误的主体。

示例:

template <typename T>
class safe_bool_concept
{
    // Implementation detail of safe bool
protected:
    ~safe_bool_concept() {}

public:
    operator safe_bool() const
    {
        return static_cast<const T*>(this)->is_null() ? ...;
    }
};

struct Foo : safe_bool_concept<Foo>
{
    ...

private:
    friend class safe_bool_concept<Foo>;
    bool is_null() const { ... }
};

然后你可以做(​​对!=做同样的事情):

template <typename T>
void operator==(const safe_bool_concept<T>& x, const safe_bool_concept<T>&)
{
    x.some_private_member(); // invalid, but won't be generated
                             // unless safe_bool classes are compared
}

这意味着如果你想禁止比较,应该通过CRTP实现安全bool习语。然而,与零的比较仍然有效。

如果您使用非会员功能路线,则必须提供<><=>=