C++ Academy · บทเรียน

std::visit

ประมวลผลทางเลือกของ variant

บทเรียน 4 จาก 413 ขั้นตอน

std::visit เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงควรใช้ std::visit

การตรวจสอบชนิดทางเลือกแต่ละชนิดด้วย get_if ด้วยตนเองทำให้โค้ดยืดยาว std::visit จะนำฟังก์ชันที่เรียกใช้ได้ไปใช้กับชนิดที่วาเรียนต์กำลังเก็บอยู่ โดยจัดการการเลือกเรียกให้คุณ

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 4;
    std::visit([](auto x){ std::cout << x << "\n"; }, v);
}

ตัวเยี่ยมชมด้วยแลมบ์ดาทั่วไป

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

#include <iostream>
#include <string>
#include <variant>
int main() {
    std::variant<int, std::string> v = std::string("hi");
    std::visit([](const auto& x){ std::cout << x << "\n"; }, v);
}

การส่งคืนค่า

std::visit สามารถส่งคืนค่าได้ ทุกแขนงต้องส่งคืนชนิดเดียวกัน

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 2.5;
    double d = std::visit([](auto x){ return x * 2.0; }, v);
    std::cout << d << "\n";
}

พฤติกรรมแยกตามชนิดด้วย if constexpr

หากต้องการให้ทำงานแตกต่างกันตามชนิดภายในแลมบ์ดาทั่วไปหนึ่งตัว ให้ใช้ if constexpr ร่วมกับ std::decay_t และ std::is_same_v

#include <iostream>
#include <string>
#include <variant>
#include <type_traits>
int main() {
    std::variant<int, std::string> v = 5;
    std::visit([](const auto& x){
        using T = std::decay_t<decltype(x)>;
        if constexpr (std::is_same_v<T, int>) std::cout << "int " << x << "\n";
        else std::cout << "str " << x << "\n";
    }, v);
}

ตัวเยี่ยมชมแบบโครงสร้าง

คุณยังสามารถเขียนโครงสร้างที่มีโอเวอร์โหลดของ operator() หลายรายการ โดยมีหนึ่งรายการต่อชนิดข้อมูล คอมไพเลอร์จะเลือกโอเวอร์โหลดที่ตรงกัน

#include <iostream>
#include <string>
#include <variant>
struct Printer {
    void operator()(int i) const { std::cout << "int " << i << "\n"; }
    void operator()(const std::string& s) const { std::cout << "str " << s << "\n"; }
};
int main() {
    std::variant<int, std::string> v = std::string("yo");
    std::visit(Printer{}, v);
}

สำนวน overloaded

ตัวช่วยที่ได้รับความนิยมนี้รวมแลมบ์ดาหลายตัวให้เป็นตัวเยี่ยมชมหนึ่งตัว แลมบ์ดาแต่ละตัวจะจัดการชนิดข้อมูลเฉพาะ

#include <iostream>
#include <string>
#include <variant>
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
int main() {
    std::variant<int, std::string> v = 8;
    std::visit(overloaded{
        [](int i){ std::cout << "i=" << i << "\n"; },
        [](const std::string& s){ std::cout << "s=" << s << "\n"; }
    }, v);
}

ความครอบคลุมทุกกรณี

ตัวเยี่ยมชมต้องจัดการกับชนิดทางเลือก ทุกชนิด มิฉะนั้นโค้ดจะคอมไพล์ไม่ผ่าน การตรวจสอบขณะคอมไพล์นี้ช่วยป้องกันการลืมกรณีใดกรณีหนึ่ง

การเยี่ยมชมและการเปลี่ยนค่า

หากส่งวาเรียนต์ด้วยการอ้างอิงที่ไม่ใช่ const ตัวเยี่ยมชมจะสามารถแก้ไขค่าที่เก็บไว้โดยตรงภายในได้

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 10;
    std::visit([](auto& x){ x += 1; }, v);
    std::cout << std::get<int>(v) << "\n";
}

วาเรียนต์หลายตัว

std::visit รับวาเรียนต์หลายตัวพร้อมกันได้ โดยตัวเยี่ยมชมจะได้รับอาร์กิวเมนต์หนึ่งรายการต่อวาเรียนต์หนึ่งตัว

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> a = 2;
    std::variant<int, double> b = 3.0;
    auto sum = std::visit([](auto x, auto y){ return x + y; }, a, b);
    std::cout << sum << "\n";
}

การเลือกรูปแบบตัวเยี่ยมชม

ใช้แลมบ์ดา auto ทั่วไปสำหรับการจัดการที่เหมือนกัน ใช้สำนวน overloaded สำหรับตรรกะที่แยกตามชนิดอย่างเป็นระเบียบ และใช้ตัวเยี่ยมชมแบบโครงสร้างเมื่อจำเป็นต้องนำพฤติกรรมกลับมาใช้ซ้ำในหลายจุดเรียก

การเยี่ยมชมเทียบกับ get_if

get_if เหมาะสำหรับการตรวจสอบอย่างรวดเร็วเพียงครั้งเดียว แต่ std::visit รองรับการขยายได้ดีกว่า โดยบังคับให้ครอบคลุมทุกกรณีและรวมตรรกะของแต่ละชนิดไว้ในที่เดียว

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ตรวจสอบความเข้าใจของคุณเกี่ยวกับ std::visit

ทบทวน

คุณได้เรียนรู้เกี่ยวกับ std::visit:

  • กระจายการเรียกสิ่งที่เรียกใช้ได้ไปยังชนิดทางเลือกที่กำลังใช้งานอยู่
  • ใช้แลมบ์ดาทั่วไป if constexpr ตัวเยี่ยมชมแบบโครงสร้าง หรือสำนวน overloaded
  • ตัวเยี่ยมชมต้องครอบคลุมทุกกรณี (ตรวจสอบขณะคอมไพล์)
  • สามารถส่งคืนค่าและเยี่ยมชมวาเรียนต์หลายตัวพร้อมกันได้
เริ่มต้นได้ฟรี

เรียนรู้ C++ ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
51
บทเรียน
203

คำถามที่พบบ่อย

บทเรียน “std::visit” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “std::visit” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “std::visit”

ประมวลผลทางเลือกของ variant คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “std::visit” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม

ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. enum class แบบมีขอบเขต
  2. ยูเนียนและความเสี่ยง
  3. std::variant
  4. std::visit
← กลับไปที่ C++ Academy