Mengapa kita membutuhkan std::nullopt [duplikat]

Kapan kita dapat menggunakan inisialisasi seragam untuk membuat std::optional<T> secara default dengan mudah?

std::optional<T> foo() {
   if (on_error)
      return {};

    // ...
}

Apakah ada kelemahan di atas yang dipecahkan oleh std::nullopt?


person Sebastian Hoffmann    schedule 16.07.2020    source sumber
comment
atau [Perbedaan antara nullptr, {} dan nullopt](stackoverflow.com/questions/47791737/   -  person underscore_d    schedule 16.07.2020


Jawaban (2)


Tidak.

Ini adalah cara yang sangat valid untuk membuat optional secara default.

Bahkan untuk penugasan, Anda dapat menyalin-menetapkan optional yang dibuat secara default dengan = {} alih-alih menggunakan std::nullopt:

cppreference sebenarnya mengatakan hal yang sama:

Batasan pada konstruktor nullopt_t ada untuk mendukung op = {}; dan op = nullopt; sebagai sintaksis untuk melepaskan objek opsional.

… seperti halnya proposal asli untuk fitur:

Perhatikan bahwa ini bukan satu-satunya cara untuk melepaskan objek opsional. Anda juga bisa menggunakan:

op = std::nullopt;

Anda mungkin bertanya pada diri sendiri mengapa std::nullopt ada. Proposal juga membahas hal ini:

itu memperkenalkan redundansi ke dalam antarmuka

[contoh serupa]

Di sisi lain, ada penggunaan di mana penggunaan nullopt tidak dapat diganti dengan notasi lain yang sesuai:

void run(complex<double> v);
void run(optional<string> v);

run(nullopt);              // pick the second overload
run({});                   // ambiguous

if (opt1 == nullopt) ...   // fine
if (opt2 == {}) ...        // illegal

bool is_engaged( optional<int> o)
{
  return bool(o);          // ok, but unclear
  return o != nullopt;     // familiar
}

Meskipun beberapa situasi bisa digunakan dengan sintaksis {}, penggunaan nullopt membuat maksud pemrogram lebih jelas. Bandingkan ini:

optional<vector<int>> get1() {
  return {};
}

optional<vector<int>> get2() {
  return nullopt;
}

optional<vector<int>> get3() {
  return optional<vector<int>>{};
}

Singkatnya, std::nullopt dapat berguna, tetapi dalam kasus Anda, ini tergantung pada gaya.

person Asteroids With Wings    schedule 16.07.2020

Apakah ada kelemahan di atas yang dipecahkan oleh std::nullopt?

Ya.

Dalam beberapa konteks, Anda mungkin ingin mengembalikan objek opsional yang dilepaskan secara kondisional (kosong, jika Anda mau) dan sintaks inisialisasi {} tidak dapat digunakan secara ambigu untuk menyimpulkan tipe std::nullopt_t. Misalnya, seperti yang tercakup dalam Kembalikan nilai Opsional dengan ?: operator, saat mengembalikan opsional kosong atau tidak kosong melalui ekspresi operator ternary:

return it != map.end() ? std::make_optional(it->second) : std::nullopt;
person dfrib    schedule 16.07.2020
comment
apakah saya benar bahwa ini hanya berlaku jika tipe pengembalian fungsi dideklarasikan sebagai auto ? - person Sebastian Hoffmann; 16.07.2020
comment
@SebastianHoffmann Tidak, Anda bahkan tidak memerlukan fungsi: wandbox.org/permlink/ICRS7wfj801CgGIf - person Thomas Sablik; 16.07.2020
comment
Pertanyaan terkait adalah tentang kasus yang berbeda. Ekspresi true Anda cocok dengan tipe pengembalian. Namun, tetap saja, {} bukanlah ekspresi yang valid di sana. - person Asteroids With Wings; 16.07.2020
comment
Ini membereskan semuanya, terima kasih - person Sebastian Hoffmann; 16.07.2020