วิธีการเรียกตัวสร้างที่ถูกต้องของประเภทแม่แบบ?


21

ในรหัสต่อไปนี้ฉันจะทำให้บรรทัดที่มีความคิดเห็นทำงานในลักษณะเดียวกับบรรทัดที่อยู่เหนือบรรทัดได้อย่างไร

Typeผมอยากจะทำให้มันเป็นโค้ดทั่วไปที่โทรคอนสตรัคที่เหมาะสมของแม่แบบ

#include <string>
#include <iostream>

template <typename Type>
struct Class
{
    Type data;
    Class(Type data) : data(data) { }
};

int main()
{
    Class<std::string> a = std::string("abc");
    // Class<std::string> b = "abc";
    std::cout << a.data << std::endl;
    return 0;
}

คำตอบ:




13
Class<std::string> b = "abc";

คือการคัดลอกเริ่มต้น มันไม่ทำงานเพราะมันจะเกี่ยวข้องกับการแปลงสองผู้ใช้กำหนด:

  • จากconst char*ไปstd::string,
  • จากการstd::stringClass<std::string>

แต่อนุญาตให้มากที่สุด

เมื่อคุณเขียน

Class<std::string> b("abc");
// or
Class<std::string> b{"abc"};

คุณใช้การกำหนดค่าเริ่มต้นโดยตรง ใช้งานได้เนื่องจากตอนนี้มีการใช้การแปลงที่ผู้ใช้กำหนดหนึ่งครั้งเท่านั้น:

  • จากการconst char*std::string

0

หากคุณสามารถเปลี่ยนได้Classคุณสามารถเพิ่มคอนสตรัคเตอร์การแปลงเทมเพลต จากนั้นคุณจะสามารถรวบรวมบรรทัดความคิดเห็นตามที่เขียนไว้ในตัวอย่างของคุณ ไม่ว่าในกรณีใดก็ตามไม่แนะนำให้ใช้การแปลงโดยนัยโดยไม่มีเหตุผลอันสมควรเนื่องจากอาจทำให้เกิดข้อบกพร่องแบบยาก (cf the C ++ Core Guidlines )

#include <string>
#include <iostream>

template <typename Type>
struct Class
{
    Type data;
    Class(Type data) : data(data) { }

    template<typename Other>
    Class(Other other_data) : data(other_data) {}
};


int main()
{
    Class<std::string> a = std::string("abc");
    Class<std::string> b = "abc";
    Class<std::string> c = a;

    std::cout << b.data << std::endl;
    return 0;
}

หากคุณสามารถใช้ C ++ 14 คุณสามารถใช้std::literals::string_literals::operator""sและลบคอนสตรัคเตอร์การแปลง จากนั้นบรรทัดของคุณจะเป็นดังนี้:

using namespace std::literals;

Class<std::string> b = "abc"s;

รหัสสดที่นี่

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