Apakah operasi "false <true" didefinisikan dengan baik?

153

Apakah spesifikasi C ++ mendefinisikan:

  1. keberadaan operator 'kurang dari' untuk parameter boolean, dan jika demikian,
  2. hasil dari permutasi 4 parameter?

Dengan kata lain, apakah hasil dari operasi berikut ditentukan oleh spesifikasi?

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

Pada pengaturan saya (Centos 7, gcc 4.8.2), kode di bawah ini mengeluarkan apa yang saya harapkan (mengingat sejarah C yang menyatakan false sebagai 0 dan true 1):

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

Sementara saya cukup yakin kebanyakan kompiler (semua?) Akan memberikan output yang sama, apakah ini diatur oleh spesifikasi C ++? Atau apakah kompiler yang membingungkan, tetapi memenuhi spesifikasi yang diizinkan untuk memutuskan bahwa benar kurang dari salah?

#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;
}
duncan
sumber
6
@ Interior Ada kegunaan yang valid. Seperti menggunakan std::minpada std::vector<bool>sebagai &&.
Angew tidak lagi bangga dengan SO
19
@ Interior jika Anda dapat menemukan pertanyaan bagus yang belum ditanyakan setelah bertahun-tahun StackOverflow, Anda berhak mendapatkan beberapa poin. Itu bukan trolling.
Mark Ransom
35
@Unterior Motivasi untuk bertanya adalah asli: Saya cukup baru untuk C ++ (berasal dari C) dan ingin menyimpan beberapa objek dalam std :: set <>. Implementasi saya terhadap operator <objek saya terutama didasarkan pada properti boolean objek, diikuti oleh properti pengidentifikasi sekunder lainnya. Ketika mengulangi set, saya ingin memastikan objek 'salah' menjadi yang utama. Sementara itu bekerja untuk saya di sini dan sekarang, saya mencari jaminan itu dijamin untuk bekerja di seluruh platform (termasuk yang tertanam) tanpa harus menggunakan penggunaan (a? 1: 0), atau serupa, di objek saya < operator.
duncan
26
Konsekuensi yang mengganggu adalah itu p <= qberarti p implies qkapan pdan qdari tipe bool!
Theodore Norvell
4
@ Technophile Agaknya yang mengganggu adalah bahwa <=mungkin secara tidak sengaja dibaca sebagai leftarrow, dan bahwa "hanya jika" (yaitu, "menyiratkan" secara material ") rightarrow kadang-kadang dikeset atau secara informal ditulis dengan cara yang sama =>(yaitu, dengan poros berlipat ganda menyerupai =) . Leftarrow bahkan kadang-kadang dibaca sebagai "jika," meskipun saya percaya ini jauh lebih jarang daripada penggunaan rightarrow untuk "hanya jika."
Eliah Kagan

Jawaban:

207

TL; DR:

Operasi didefinisikan dengan baik sesuai dengan standar rancangan C ++.

Detail

Kita dapat melihat bahwa dengan masuk ke draft standar C ++ bagian 5.9 Operator relasional yang mengatakan ( penekanan tambang ke depan ):

The operan harus memiliki aritmatika , pencacahan, atau penunjuk jenis , atau jenis std :: nullptr_t. Operator <(kurang dari),> (lebih besar dari), <= (kurang dari atau sama dengan), dan> = (lebih besar dari atau sama dengan) semua menghasilkan false atau true. Jenis hasilnya adalah bool

dan bool adalah tipe arithematic dari 3.9.1 tipe fundamental

Jenis bool , char, char16_t, char32_t, wchar_t, dan tipe integer yang ditandatangani dan tidak ditandatangani secara kolektif disebut tipe integral.

dan

Tipe integral dan mengambang secara kolektif disebut tipe aritmatika.

dan truedan falseadalah boolean literals dari 2.14.6Boolean literals:

boolean-literal:
    false
    true

Kembali ke bagian 5.9untuk melihat mekanisme operator relasional lebih lanjut, dikatakan:

Konversi aritmatika biasa dilakukan pada operan tipe aritmatika atau enumerasi.

yang konversi aritmatika biasa dibahas dalam bagian 5yang mengatakan:

Jika tidak, promosi integral (4,5) harus dilakukan pada kedua operan

dan bagian 4.5mengatakan:

Nilai awal tipe bool dapat dikonversi ke nilai awal tipe int, dengan false menjadi nol dan benar menjadi satu.

dan demikian pula ungkapannya:

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

menggunakan aturan ini menjadi:

0 < 0
0 < 1
1 < 0
1 < 1
Shafik Yaghmour
sumber
6
Bagus, kira-kira sejelas mungkin jawaban apa pun, sementara masih mudah dibaca. A nit: Saya pikir Anda menebalkan "tipe" yang salah: " Operand harus memiliki aritmatika , enumerasi, atau tipe pointer , atau ketik std :: nullptr_t." Menambahkan tanda kurung untuk memberikan kejelasan ((aritmatika, enumerasi, atau pointer) tipe) atau (tipe std :: nullptr_t).
Bukan berarti itu mengubah jawaban Anda, tetapi N3485 [over.built] / 12: Untuk setiap pasangan aritmatika tipe L dan R yang dipromosikan, terdapat fungsi fungsi kandidat dari bentuk ... bool operator <(L, R); - Bukankah argumen dipromosikan sebelum aturan yang Anda kutip bahkan berlaku?
chris
@ Chris Saya tidak terlalu akrab dengan bagian itu jadi saya harus memikirkannya tapi saya pikir jawabannya tidak berubah dari apa yang bisa saya lihat.
Shafik Yaghmour
Ya, promosi adalah hal pertama yang terjadi.
chris
63

Nilai Boolean tunduk pada promosi integer biasa, dengan falsedidefinisikan sebagai 0dan truedidefinisikan sebagai 1. Itu membuat semua perbandingan didefinisikan dengan baik.

Mark tebusan
sumber
2
... dan operator relasional ditentukan untuk melakukan konversi aritmatika yang biasa (yang mencakup promosi bilangan bulat) pada operan tipe aritmatika atau enumerasi.
TC
5
Saya suka bahwa jawaban ini lebih pendek daripada Shafik, tetapi saya pikir poin kunci yang falsedidefinisikan sebagai 0dan truedidefinisikan 1 dalam standar (bukan hanya oleh praktik umum) perlu bukti untuk mendukungnya.
KRyan
@ KRyan apa, Anda tidak akan mengambil kata saya untuk itu? :) Sebelum ada booltipe, bahkan sebelum ada C ++, hasil dari operasi boolean didefinisikan sebagai 0false dan 1true. Saya tidak akan terkejut jika Anda dapat menemukannya di K + R.
Mark Ransom
1
@Ryan Saya tidak bisa kembali sejauh K + R, tapi saya menggali salinan Standar ANSI C 1990 saya. Bagian 6.3.8 mengatakan "Masing-masing operator <(kurang dari), >(lebih besar dari), <=(kurang dari atau sama dengan), dan >=(lebih besar dari atau sama dengan) akan menghasilkan 1 jika hubungan yang ditentukan benar dan 0 jika itu adalah salah. Hasilnya bertipe int. "
Mark Ransom
1
Masalah terbesar IIRC adalah bahwa dalam K&R, enum bool { false = 0, true = 1}adalah legal tetapi tidak mendefinisikan suatu operator<.
MSalters
22

Menurut Standar C ++ (5.9 Operator relasional)

2 Konversi aritmatika yang biasa dilakukan pada operan tipe aritmatika atau enumerasi.

dan

1 ... Jenis hasilnya adalah bool.

dan (3.9.1 Jenis fundamental)

6 Nilai tipe bool benar atau salah.49 [Catatan: Tidak ada tipe atau nilai bool yang ditandatangani, tidak ditandatangani, pendek atau panjang. —Kirim catatan] Nilai bool jenis berpartisipasi dalam promosi integral (4.5).

dan (4,5 promosi integral)

6 Nilai awal tipe bool dapat dikonversi menjadi nilai awal tipe int, dengan false menjadi nol dan benar menjadi satu .

Jadi, dalam semua contoh Anda true dikonversi ke int 1 dan false dikonversi ke int 0

Ungkapan-ungkapan ini

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

sepenuhnya setara dengan

0 < 0
0 < 1
1 < 0
1 < 1
Vlad dari Moskow
sumber
8

Boolean falsesetara dengan int 0, dan boolean truesetara dengan int 1. Jadi ini menjelaskan mengapa ekspresi false < true=> 0 < 1adalah satu-satunya yang mengembalikan true.

Blindstealer
sumber