我还有另外一个与安全布尔成语有关的问题:
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_comparisons
为const
?
无论如何,没有人应该通过返回指针实际调用成员函数,对吗?
这里需要const
吗? operator bool_type
(成员函数)是否会违反const-correctness?
答案 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。提问:
有人不太明白他们编码的是什么。或者也许他们打算限制通话的能力,一点点。但是,这非常徒劳无功。
右。
没有
没有
干杯&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习语。然而,与零的比较仍然有效。
如果您使用非会员功能路线,则必须提供<
,>
,<=
和>=
。