การดำเนินการ "false <true" ถูกกำหนดอย่างดีหรือไม่


153

ข้อกำหนด C ++ กำหนดไว้หรือไม่:

  1. การมีอยู่ของตัวดำเนินการ 'น้อยกว่า' สำหรับพารามิเตอร์บูลีนและหากเป็นเช่นนั้น
  2. ผลลัพธ์ของการเปลี่ยนลำดับพารามิเตอร์ 4 รายการคืออะไร?

กล่าวอีกนัยหนึ่งผลลัพธ์จากการดำเนินการต่อไปนี้ถูกกำหนดโดยสเปคหรือไม่

false < false
false < true
true < false
true < true

ในการตั้งค่าของฉัน (Centos 7, gcc 4.8.2) โค้ดด้านล่างจะแยกแยะสิ่งที่ฉันคาดหวัง (จากประวัติของ C ในการแทน false เป็น 0 และ true เป็น 1):

false < false = false
false < true = true
true < false = false
true < true = false

ในขณะที่ฉันค่อนข้างแน่ใจว่าคอมไพเลอร์ (ทั้งหมด?) ส่วนใหญ่จะให้ผลลัพธ์เดียวกันนี่คือข้อกำหนดของ C ++ หรือไม่ หรือเป็นสิ่งที่ทำให้งงงง แต่คอมไพเลอร์ตามข้อกำหนดได้รับอนุญาตให้ตัดสินใจว่าจริงน้อยกว่าเท็จ?

#include <iostream>

const char * s(bool a)
{
  return (a ? "true" : "false");
}

void test(bool a, bool b)
{
  std::cout << s(a) << " < " << s(b) << " = " << s(a < b) << std::endl;
}

int main(int argc, char* argv[])
{
  test(false, false);
  test(false, true);
  test(true, false);
  test(true, true);
  return 0;
}

6
@Ulterior มีการใช้ที่ถูกต้องอยู่ เช่นการใช้std::minในการเป็นstd::vector<bool> &&
Angew ไม่ภูมิใจใน SO SO

19
@ ล่วงหน้าถ้าคุณสามารถหาคำถามที่ดีที่ยังไม่ได้รับการถามหลังจาก StackOverflow ทุกปีคุณสมควรได้รับบางจุด มันไม่ได้หลอก
Mark Ransom

35
@ ล้าสมัยแรงจูงใจในการถามเป็นของแท้: ฉันค่อนข้างใหม่กับ C ++ (มาจาก C) และต้องการเก็บวัตถุบางอย่างใน std :: set <> การใช้งานตัวดำเนินการ <ของวัตถุของฉันเป็นไปตามหลักในคุณสมบัติบูลีนของวัตถุตามด้วยคุณสมบัติการระบุรองอื่น ๆ เมื่อวนซ้ำชุดฉันต้องการให้แน่ใจว่าวัตถุ 'เท็จ' มาก่อน ในขณะที่ใช้งานได้สำหรับฉันที่นี่และตอนนี้ฉันกำลังมองหาความมั่นใจว่าจะรับประกันการทำงานข้ามแพลตฟอร์ม (รวมถึงที่ฝังตัว) โดยไม่ต้องหันไปใช้ (a? 1: 0) โดยไม่จำเป็นในวัตถุของฉัน ผู้ประกอบการ
แคน

26
ผลที่ตามมาก็คือนั่นp <= qหมายถึงp implies qเวลาpและqประเภทบูล!
Theodore Norvell

4
@Technophile น่าจะเป็นสิ่งที่รบกวนก็คือ<=อาจจะอ่านโดยไม่ได้ตั้งใจเป็น leftarrow และ "ถ้า" (เช่น "[หมายถึง" [นัยสำคัญ] หมายถึง) rightarrow บางครั้งเรียงพิมพ์หรือเขียนคล้ายกับ=>(กล่าวคือคล้ายกับเพลาสองเท่า=) . บางครั้งคนที่เหลือก็อ่านว่า "ถ้า" แม้ว่าฉันจะเชื่อว่าสิ่งนี้เป็นเรื่องธรรมดาน้อยกว่าการใช้ลูกศรขวาสำหรับ "เฉพาะในกรณี"
Eliah Kagan

คำตอบ:


207

TL; DR:

การดำเนินการถูกกำหนดไว้อย่างดีตามมาตรฐาน C ++ แบบร่าง

รายละเอียด

เราจะเห็นได้ว่าโดยไปที่ร่างมาตรฐาน C ++ส่วน5.9 ผู้ดำเนินการเชิงสัมพันธ์ซึ่งพูดว่า ( เน้นการทำเหมืองไปข้างหน้า ):

ตัวถูกดำเนินการจะต้องมีเลขคณิตนับหรือตัวชี้ประเภทหรือชนิดมาตรฐาน :: nullptr_t ตัวดำเนินการ <(น้อยกว่า),> (มากกว่า), <= (น้อยกว่าหรือเท่ากับ) และ> = (มากกว่าหรือเท่ากับ) ทั้งหมดให้ผลเป็นเท็จหรือจริง ประเภทของผลลัพธ์คือบูล

และคนโง่เป็นประเภทคณิตศาสตร์จาก 3.9.1 ประเภทพื้นฐาน

ประเภทbool , char, char16_t, char32_t, wchar_t และประเภทจำนวนเต็มที่ลงนามและไม่ได้ลงนามจะ เรียกว่าประเภทรวม

และ

ประเภทอินทิกรัลและแบบลอยเรียกรวมกันว่าประเภททางคณิตศาสตร์

และtrueและfalseมีตัวอักษรแบบบูลจาก2.14.6ตัวอักษรแบบบูล:

boolean-literal:
    false
    true

กลับไปที่ส่วน5.9เพื่อดูกลไกของผู้ประกอบการสัมพันธ์เพิ่มเติมกล่าวว่า:

การแปลงเลขคณิตปกติจะดำเนินการกับตัวถูกดำเนินการทางคณิตศาสตร์หรือประเภทการแจงนับ

การแปลงเลขคณิตปกติจะครอบคลุมในส่วน5ที่ระบุว่า:

มิฉะนั้นการส่งเสริมการขายที่สมบูรณ์ (4.5) จะต้องดำเนินการกับตัวถูกดำเนินการทั้งสอง

และส่วน4.5พูดว่า:

prvalue ของบูลชนิดสามารถแปลงเป็น prvalue ของ type int โดยมีค่าเป็นศูนย์และกลายเป็นค่าจริง

และการแสดงออก:

false < false
false < true
true < false
true < true

ใช้กฎเหล่านี้กลายเป็น:

0 < 0
0 < 1
1 < 0
1 < 1

6
Nice นั่นเป็นคำตอบที่ชัดเจนพอ ๆ กับที่อ่านได้ง่าย A นิดหน่อย: ฉันคิดว่าคุณทำตัวหนาผิด "พิมพ์": " ตัวถูกดำเนินการจะต้องมีเลขคณิต , แจงนับหรือชี้ประเภทหรือพิมพ์ std :: nullptr_t" การเพิ่มวงเล็บเพื่อความชัดเจนให้ประเภท ((คณิตศาสตร์, การแจงนับหรือตัวชี้)) หรือ (type std :: nullptr_t)

ไม่ใช่ว่ามันจะเปลี่ยนคำตอบของคุณ แต่ N3485 [over.built] / 12: สำหรับคู่เลขคณิตที่ได้รับการเลื่อนประเภท L และ R ทุกคู่จะมีฟังก์ชั่นตัวดำเนินการตัวเลือกของแบบฟอร์ม ... ตัวดำเนินการ bool <(L, R); - ข้อโต้แย้งที่ไม่ได้รับการส่งเสริมก่อนกฎที่คุณอ้างถึงจะนำไปใช้ใช่หรือไม่
chris

@ Chris ฉันไม่คุ้นเคยเป็นอย่างยิ่งกับส่วนนั้นดังนั้นฉันจะต้องคิดถึงมัน แต่ฉันไม่คิดว่าคำตอบจะเปลี่ยนไปจากสิ่งที่ฉันเห็น
Shafik Yaghmour

ใช่การส่งเสริมเป็นสิ่งแรกที่เกิดขึ้นไม่ทางใดก็ทางหนึ่ง
chris

63

ค่าบูลีนจะขึ้นอยู่กับโปรโมชั่นจำนวนเต็มปกติมีfalseกำหนดเป็น0และกำหนดให้เป็นtrue 1นั่นทำให้การเปรียบเทียบทั้งหมดถูกนิยามอย่างดี


2
... และตัวดำเนินการสัมพันธ์ถูกระบุเพื่อดำเนินการแปลงเลขคณิตตามปกติ
TC

5
ฉันชอบคำตอบนี้สั้นกว่าของ Shafik แต่ฉันคิดว่าประเด็นสำคัญที่falseกำหนดไว้0และtrueถูกกำหนดไว้1 ในมาตรฐาน (แทนที่จะเป็นเพียงแค่การปฏิบัติทั่วไป) ต้องมีหลักฐานเพื่อสำรองข้อมูล
KRyan

@Kyan อะไรคุณจะไม่ใช้คำของฉันมันได้หรือไม่ :) ก่อนที่จะมีboolประเภทก่อนที่จะมีแม้แต่ C ++ ผลลัพธ์ของการดำเนินการบูลีนถูกกำหนดเป็น0เท็จและ1เป็นจริง ฉันจะไม่แปลกใจถ้าคุณสามารถค้นหาได้ใน K + R
Mark Ransom

1
@Kyan ฉันไม่สามารถย้อนกลับไปได้ไกลเท่าที่ K + R แต่ฉันขุดสำเนามาตรฐาน ANSI C ปี 1990 ของฉัน มาตรา 6.3.8 กล่าวว่า "ผู้ดำเนินการแต่ละคน<(น้อยกว่า), >(มากกว่า), <=(น้อยกว่าหรือเท่ากับ) และ>=(มากกว่าหรือเท่ากับ) จะให้ผลตอบแทน 1 หากความสัมพันธ์ที่ระบุเป็นจริงและ 0 ถ้าเป็น false ผลลัพธ์มีประเภทint"
Mark Ransom

1
ปัญหาที่ใหญ่ที่สุดคือการที่ IIRC ใน K & R, enum bool { false = 0, true = 1}ถูกกฎหมาย operator<แต่ไม่ได้กำหนด
MSalters

22

ตามมาตรฐาน C ++ (ผู้ประกอบการสัมพันธ์ 5.9)

2 การแปลงเลขคณิตปกติจะดำเนินการกับตัวถูกดำเนินการทางคณิตศาสตร์หรือประเภทการแจงนับ

และ

1 ... ประเภทของผลลัพธ์คือบูล

และ (3.9.1 ประเภทพื้นฐาน)

6 ค่าประเภทบูลอาจเป็นจริงหรือเท็จ 49 [หมายเหตุ: ไม่มีประเภทหรือค่าบูลที่ลงชื่อ, ไม่ได้ลงชื่อ, สั้นหรือยาว - บันทึกย่อ] ค่าประเภทบูลมีส่วนร่วมในการส่งเสริมการขายหนึ่งรายการ (4.5)

และ (4.5 การส่งเสริมการขายแบบรวม)

6 prvalue ประเภทบูลสามารถแปลงเป็น prvalue ชนิด int กับเท็จกลายเป็นศูนย์และเป็นความจริงกลายเป็นหนึ่ง

ดังนั้นในตัวอย่างทั้งหมดของคุณถูกแปลงเป็น int 1 และ false ถูกแปลงเป็น int 0

การแสดงออกเหล่านี้

false < false
false < true
true < false
true < true

ทั้งหมดเทียบเท่า

0 < 0
0 < 1
1 < 0
1 < 1

8

บูลีนfalseเทียบเท่ากับint 0และบูลเทียบเท่ากับtrue int 1ดังนั้นนี้จะอธิบายว่าทำไมการแสดงออกfalse < true=> เป็นเพียงคนเดียวที่ผลตอบแทน0 < 1true

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.