ทำไมเราต้อง std::nullopt [ซ้ำกัน]

เมื่อเราสามารถใช้การกำหนดค่าเริ่มต้นแบบสม่ำเสมอเพื่อเริ่มต้นสร้าง std::optional<T> ได้อย่างง่ายดาย

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

    // ...
}

มีข้อเสียเปรียบใด ๆ ที่ std::nullopt แก้ไขข้างต้นหรือไม่


person Sebastian Hoffmann    schedule 16.07.2020    source แหล่งที่มา
comment
หรือ [ความแตกต่างระหว่าง nullptr, {} และ nullopt](stackoverflow.com/questions/47791737/   -  person underscore_d    schedule 16.07.2020


คำตอบ (2)


ไม่

นี่เป็นวิธีที่ถูกต้องสมบูรณ์ในการสร้างค่าเริ่มต้น optional

แม้กระทั่งสำหรับการมอบหมายงาน คุณสามารถคัดลอกมอบหมาย optional ที่สร้างโดยค่าเริ่มต้นด้วย = {} แทนที่จะใช้ std::nullopt:

cppreference จริงๆ แล้ว พูดได้มาก:

ข้อจำกัดในตัวสร้างของ nullopt_t มีอยู่เพื่อรองรับทั้ง op = {}; และ op = nullopt; เป็นไวยากรณ์สำหรับการแยกอ็อบเจ็กต์ทางเลือก

… เช่นเดียวกับ ข้อเสนอดั้งเดิมสำหรับ คุณลักษณะ:

โปรดทราบว่าไม่ใช่วิธีเดียวที่จะปลดออบเจ็กต์เสริมได้ คุณยังสามารถใช้:

op = std::nullopt;

คุณอาจถามตัวเองว่าทำไม std::nullopt ถึงมีอยู่เลย ข้อเสนอ กล่าวถึงเรื่องนี้ด้วย< /ก>:

มันแนะนำความซ้ำซ้อนในอินเทอร์เฟซ

[ตัวอย่างที่คล้ายกัน]

ในทางกลับกัน มีการใช้งานที่ไม่สามารถแทนที่การใช้ nullopt ด้วยสัญกรณ์ที่สะดวกอื่น ๆ ได้:

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
}

แม้ว่าบางสถานการณ์จะใช้ได้กับไวยากรณ์ {} แต่การใช้ nullopt จะทำให้ความตั้งใจของโปรแกรมเมอร์ชัดเจนยิ่งขึ้น เปรียบเทียบสิ่งเหล่านี้:

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

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

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

กล่าวโดยสรุป std::nullopt อาจมีประโยชน์ แต่ในกรณีของคุณ มันขึ้นอยู่กับสไตล์เท่านั้น

person Asteroids With Wings    schedule 16.07.2020

มีข้อเสียเปรียบใด ๆ ที่ std::nullopt แก้ไขข้างต้นหรือไม่

ใช่.

ในบางบริบท คุณอาจต้องการส่งคืนออบเจ็กต์เสริมที่ปลดการเชื่อมต่ออย่างมีเงื่อนไข (ว่างเปล่า หากคุณต้องการ) และไวยากรณ์การเริ่มต้น {} ไม่สามารถใช้แบบไม่คลุมเครือเพื่ออนุมานประเภท std::nullopt_t ได้ เช่น ตามที่อธิบายไว้ใน ส่งคืนค่าเสริมด้วย ?: โอเปอเรเตอร์ เมื่อส่งคืนตัวเลือกว่างหรือไม่ว่างผ่านนิพจน์ตัวดำเนินการแบบไตรภาค:

return it != map.end() ? std::make_optional(it->second) : std::nullopt;
person dfrib    schedule 16.07.2020
comment
ฉันถูกต้องหรือไม่ว่าสิ่งนี้ใช้ได้เฉพาะเมื่อมีการประกาศประเภทการส่งคืนของฟังก์ชันเป็น auto เท่านั้น - person Sebastian Hoffmann; 16.07.2020
comment
@SebastianHoffmann ไม่ คุณไม่จำเป็นต้องมีฟังก์ชันด้วยซ้ำ: wandbox.org/permlink/ICRS7wfj801CgGIf - person Thomas Sablik; 16.07.2020
comment
คำถามที่เชื่อมโยงเป็นเรื่องเกี่ยวกับกรณีอื่น นิพจน์ true ของคุณตรงกับประเภทการส่งคืน แต่ถึงกระนั้น {} ก็ไม่ใช่นิพจน์ที่ถูกต้อง - person Asteroids With Wings; 16.07.2020
comment
สิ่งนี้ทำให้สิ่งต่าง ๆ ชัดเจนขึ้น ขอบคุณ - person Sebastian Hoffmann; 16.07.2020