ความหมายของ“ operator bool () const” คืออะไร


คำตอบ:


145

ฟังก์ชันสมาชิกของแบบฟอร์ม

operator TypeName()

เป็นตัวดำเนินการแปลง อนุญาตให้ใช้อ็อบเจ็กต์ประเภทคลาสราวกับว่าเป็นประเภทTypeNameและเมื่อเป็นเช่นนั้นพวกเขาจะถูกแปลงเป็นการTypeNameใช้ฟังก์ชันการแปลง

ในกรณีนี้operator bool()อนุญาตให้ใช้อ็อบเจ็กต์ประเภทคลาสราวกับว่าเป็นไฟล์bool. ตัวอย่างเช่นหากคุณมีออบเจ็กต์ประเภทคลาสที่ตั้งชื่อobjคุณสามารถใช้เป็น

if (obj)

สิ่งนี้จะเรียกใช้operator bool()ส่งคืนผลลัพธ์และใช้ผลลัพธ์เป็นเงื่อนไขของif.

ควรสังเกตว่าoperator bool()เป็นความคิดที่แย่มากและคุณไม่ควรใช้มันเลย สำหรับคำอธิบายโดยละเอียดว่าเหตุใดจึงไม่ดีและสำหรับวิธีแก้ไขปัญหาโปรดดู"The Safe Bool Idiom"

(C ++ 0x ซึ่งเป็นการแก้ไขมาตรฐาน C ++ ที่กำลังจะมีขึ้นเพิ่มการสนับสนุนสำหรับตัวดำเนินการแปลงอย่างชัดเจนสิ่งเหล่านี้จะช่วยให้คุณสามารถเขียนตู้นิรภัยexplicit operator bool()ที่ทำงานได้อย่างถูกต้องโดยไม่ต้องข้ามห่วงการใช้งาน Safe Bool Idiom)


1
"ใช้ราวกับว่ามันเป็นบูล" โดยนัยที่เป็นเท็จคุณสามารถพูดและกำหนดค่าบูลีนได้ แต่ในโค้ดของโปสเตอร์จะสร้างตัวแปรชั่วคราวประเภทบูลที่เกี่ยวข้องกับค่าโมเมนต์ของ col แต่หลังจากนั้นจะไม่ขึ้นกับอ็อบเจ็กต์ที่สร้างขึ้น นอกจากนี้การกล่าวถึง Safe Bool Idiom นั้นยอดเยี่ยม แต่เพียงเพื่อลงทะเบียนว่ามีมุมมองที่ตรงกันข้ามอยู่: IMHO คำแนะนำ "ไม่เคยใช้จริงๆ" อยู่ด้านบน - จะให้การตรวจสอบคอมไพเลอร์ที่เข้มงวดขึ้นเพื่อป้องกันการใช้งานในทางที่ผิดโดยเสียค่า API ที่ซับซ้อนมากขึ้น ที่อาจนำไปสู่การใช้ในทางที่ผิดโดยไม่ได้ตั้งใจ
Tony Delroy

1
@ โทนี่: ก็ใช้ได้เหมือนบูล; เนื่องจากผลลัพธ์ของการแปลงเป็น rvalue ( bool) ไม่คุณจึงไม่สามารถกำหนดให้ได้ หากเป็นค่า lvalue ที่ปรับเปลี่ยนได้ (เช่นbool&) คุณสามารถกำหนดให้ได้ สำหรับความถูกต้องฉันยืนยันว่า an operator bool()ไม่ถูกต้องเสมอเพราะอนุญาตให้ใช้ออบเจ็กต์ประเภทคลาสในสถานการณ์จำนวนมากที่คุณไม่ต้องการใช้ Safe Bool เป็นทางเลือกที่เหนือกว่า
James McNellis

1
explicit operator bool()ดังนั้นตามวรรคสุดท้ายวันนี้เป็นวันที่ดีที่สุดที่ตกลงเพื่อการใช้งาน ฉันเข้าใจถูกต้องหรือไม่?
Zingam

1
ดูเหมือนว่าคณะกรรมการ C ++ จะไม่เห็นด้วยกับคุณในการดำเนินการบูล () อย่างน้อยสำหรับเวอร์ชันล่าสุดของมาตรฐาน (เช่นen.cppreference.com/w/cpp/utility/optional ) หรือบางทีคุณอาจหมายถึงรหัส STL เท่านั้นที่ควรได้รับอนุญาตให้ใช้?
Joe Steele

2
@JoeSteele - ดูstackoverflow.com/a/16615725/2492801 ตัวดำเนินการแปลงที่ชัดเจนปลอดภัย!
Benjamin Bihler

9
operator bool() const 
{
    return col != 0;
}

กำหนดว่าคลาสสามารถแปลงเป็นค่าบูลีนได้อย่างไรconstหลังจากที่()ใช้เพื่อระบุวิธีนี้จะไม่กลายพันธุ์ (เปลี่ยนสมาชิกของคลาสนี้)

โดยปกติคุณจะใช้ตัวดำเนินการดังต่อไปนี้:

airplaysdk sdkInstance;
if (sdkInstance) {
    std::cout << "Instance is active" << std::endl;
} else {
    std::cout << "Instance is in-active error!" << std::endl;
}

7

ฉันต้องการให้รหัสเพิ่มเติมเพื่อให้ชัดเจน

struct A
{
    operator bool() const { return true; }
};

struct B
{
    explicit operator bool() const { return true; }
};

int main()
{
    A a1;
    if (a1) cout << "true" << endl; // OK: A::operator bool()
    bool na1 = a1; // OK: copy-initialization selects A::operator bool()
    bool na2 = static_cast<bool>(a1); // OK: static_cast performs direct-initialization

    B b1;     
    if (b1) cout << "true" << endl; // OK: B::operator bool()
    // bool nb1 = b1; // error: copy-initialization does not consider B::operator bool()
    bool nb2 = static_cast<bool>(b1); // OK: static_cast performs direct-initialization
}

3

เป็นimplicitฟังก์ชันการแปลงที่ผู้ใช้กำหนดเองเพื่อแปลงคลาสของคุณเป็นtrueหรือfalse.

//usage
bool value = yourclassinstance; //yourclassinstance is converted into bool!

1

boolมันเป็นแปลงนัยไป เช่นเมื่อใดก็ตามที่อนุญาตให้มีการแปลงโดยนัยชั้นเรียนของคุณสามารถแปลงเป็นboolโดยเรียกใช้วิธีการนั้น


1

ดังที่คนอื่น ๆ กล่าวไว้สำหรับการแปลงประเภทในกรณีนี้เป็นboolไฟล์. ตัวอย่างเช่น:

class A {
    bool isItSafe;

public:
    operator bool() const
    {
        return isItSafe;
    }

    ...
};

ตอนนี้ฉันสามารถใช้ออบเจ็กต์ของคลาสนี้ราวกับว่ามันเป็นบูลีน:

A a;
...
if (a) {
    ....
}

1

เมื่อเขียน unique_ptr ของฉันเองฉันพบกรณีนี้ ได้รับstd::unique_ptr'soperator== :

template<class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

template <class T, class D>
bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;

template <class T, class D>
bool operator==(nullptr_t, const unique_ptr<T, D>& x) noexcept;

และกรณีทดสอบจากlibstdcxx :

  std::unique_ptr<int> ptr;
  if (ptr == 0)
    { }
  if (0 == ptr)
    { }
  if (ptr != 0)
    { }
  if (0 != ptr)
    { }

สังเกตว่าptrมี a explicit operator bool() const noexcept;จึงoperator overload resolutionใช้ได้ดีที่นี่เช่นptr == 0เลือก

 template <class T, class D>
 bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;`.

หากไม่มีexplicitคำหลักที่นี่ptrในptr == 0จะถูกแปลงเป็นboolจากนั้นboolจะถูกแปลงเป็นintเพราะbool operator==(int, int)มีอยู่แล้วภายในและ0เป็นintเป็นสิ่งที่รอเราอยู่คือข้อผิดพลาดในการแก้ปัญหาโอเวอร์โหลดที่ไม่ชัดเจน

นี่คือตัวอย่างขั้นต่ำสมบูรณ์และตรวจสอบได้ :

#include <cstddef>
struct A
{
    constexpr A(std::nullptr_t) {}
    operator bool() 
    {
        return true;
    }
};

constexpr bool operator ==(A, A) noexcept
{
    return true;
}

constexpr bool operator ==(A, std::nullptr_t) noexcept
{
    return true;
}

constexpr bool operator ==(std::nullptr_t, A) noexcept
{
    return true;
}

int main()
{
    A a1(nullptr);
    A a2(0);
    a1 == 0;
}

gcc :

prog.cc: In function 'int main()':
prog.cc:30:8: error: ambiguous overload for 'operator==' (operand types are 'A' and 'int')
   30 |     a1 == 0;
      |     ~~ ^~ ~
      |     |     |
      |     A     int
prog.cc:30:8: note: candidate: 'operator==(int, int)' <built-in>
   30 |     a1 == 0;
      |     ~~~^~~~
prog.cc:11:16: note: candidate: 'constexpr bool operator==(A, A)'
   11 | constexpr bool operator ==(A, A) noexcept
      |                ^~~~~~~~
prog.cc:16:16: note: candidate: 'constexpr bool operator==(A, std::nullptr_t)'
   16 | constexpr bool operator ==(A, std::nullptr_t) noexcept
      |                ^~~~~~~~

เสียงดัง :

prog.cc:30:8: error: use of overloaded operator '==' is ambiguous (with operand types 'A' and 'int')
    a1 == 0;
    ~~ ^  ~
prog.cc:16:16: note: candidate function
constexpr bool operator ==(A, std::nullptr_t) noexcept
               ^
prog.cc:11:16: note: candidate function
constexpr bool operator ==(A, A) noexcept
               ^
prog.cc:30:8: note: built-in candidate operator==(int, int)
    a1 == 0;
       ^
prog.cc:30:8: note: built-in candidate operator==(float, int)
prog.cc:30:8: note: built-in candidate operator==(double, int)
prog.cc:30:8: note: built-in candidate operator==(long double, int)
prog.cc:30:8: note: built-in candidate operator==(__float128, int)
prog.cc:30:8: note: built-in candidate operator==(int, float)
prog.cc:30:8: note: built-in candidate operator==(int, double)
prog.cc:30:8: note: built-in candidate operator==(int, long double)
prog.cc:30:8: note: built-in candidate operator==(int, __float128)
prog.cc:30:8: note: built-in candidate operator==(int, long)
prog.cc:30:8: note: built-in candidate operator==(int, long long)
prog.cc:30:8: note: built-in candidate operator==(int, __int128)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long, int)
prog.cc:30:8: note: built-in candidate operator==(long long, int)
prog.cc:30:8: note: built-in candidate operator==(__int128, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, int)
prog.cc:30:8: note: built-in candidate operator==(float, float)
prog.cc:30:8: note: built-in candidate operator==(float, double)
prog.cc:30:8: note: built-in candidate operator==(float, long double)
prog.cc:30:8: note: built-in candidate operator==(float, __float128)
prog.cc:30:8: note: built-in candidate operator==(float, long)
prog.cc:30:8: note: built-in candidate operator==(float, long long)
prog.cc:30:8: note: built-in candidate operator==(float, __int128)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(double, float)
prog.cc:30:8: note: built-in candidate operator==(double, double)
prog.cc:30:8: note: built-in candidate operator==(double, long double)
prog.cc:30:8: note: built-in candidate operator==(double, __float128)
prog.cc:30:8: note: built-in candidate operator==(double, long)
prog.cc:30:8: note: built-in candidate operator==(double, long long)
prog.cc:30:8: note: built-in candidate operator==(double, __int128)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long double, float)
prog.cc:30:8: note: built-in candidate operator==(long double, double)
prog.cc:30:8: note: built-in candidate operator==(long double, long double)
prog.cc:30:8: note: built-in candidate operator==(long double, __float128)
prog.cc:30:8: note: built-in candidate operator==(long double, long)
prog.cc:30:8: note: built-in candidate operator==(long double, long long)
prog.cc:30:8: note: built-in candidate operator==(long double, __int128)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(__float128, float)
prog.cc:30:8: note: built-in candidate operator==(__float128, double)
prog.cc:30:8: note: built-in candidate operator==(__float128, long double)
prog.cc:30:8: note: built-in candidate operator==(__float128, __float128)
prog.cc:30:8: note: built-in candidate operator==(__float128, long)
prog.cc:30:8: note: built-in candidate operator==(__float128, long long)
prog.cc:30:8: note: built-in candidate operator==(__float128, __int128)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long, float)
prog.cc:30:8: note: built-in candidate operator==(long, double)
prog.cc:30:8: note: built-in candidate operator==(long, long double)
prog.cc:30:8: note: built-in candidate operator==(long, __float128)
prog.cc:30:8: note: built-in candidate operator==(long, long)
prog.cc:30:8: note: built-in candidate operator==(long, long long)
prog.cc:30:8: note: built-in candidate operator==(long, __int128)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long long, float)
prog.cc:30:8: note: built-in candidate operator==(long long, double)
prog.cc:30:8: note: built-in candidate operator==(long long, long double)
prog.cc:30:8: note: built-in candidate operator==(long long, __float128)
prog.cc:30:8: note: built-in candidate operator==(long long, long)
prog.cc:30:8: note: built-in candidate operator==(long long, long long)
prog.cc:30:8: note: built-in candidate operator==(long long, __int128)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(__int128, float)
prog.cc:30:8: note: built-in candidate operator==(__int128, double)
prog.cc:30:8: note: built-in candidate operator==(__int128, long double)
prog.cc:30:8: note: built-in candidate operator==(__int128, __float128)
prog.cc:30:8: note: built-in candidate operator==(__int128, long)
prog.cc:30:8: note: built-in candidate operator==(__int128, long long)
prog.cc:30:8: note: built-in candidate operator==(__int128, __int128)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned __int128)
1 error generated.

-4

การใช้งานทั่วไปอีกอย่างหนึ่งสำหรับคอนเทนเนอร์ std เพื่อทำการเปรียบเทียบความเท่าเทียมกันของค่าคีย์ภายในออบเจ็กต์ที่กำหนดเอง

class Foo
{
    public: int val;
};

class Comparer { public:
bool operator () (Foo& a, Foo&b) const {
return a.val == b.val; 
};

class Blah
{
std::set< Foo, Comparer > _mySet;
};

2
นี่คือตัวอย่างการใช้งานไม่ได้operator () operator boolพวกเขาแตกต่างกันโดยสิ้นเชิง operator ()เป็นตัวดำเนินการโทรเพื่อให้Comparerสามารถเรียกใช้เป็นฟังก์ชันได้ สิ่งนี้operator ()เกิดขึ้นเพื่อกลับมาboolแต่นั่นไม่ได้ทำให้มันเหมือนกับoperator boolที่อนุญาตให้ส่งโดยปริยายboolได้
Michael Dorst
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.