จะสร้างฟังก์ชั่นเทมเพลตภายในคลาสได้อย่างไร? (C ++)


144

ฉันรู้ว่าเป็นไปได้ที่จะสร้างฟังก์ชันแม่แบบ:

template<typename T>
void DoSomeThing(T x){}

และเป็นไปได้ที่จะสร้างคลาสเทมเพลต:

template<typename T>
class Object
{
public:
    int x;
};

แต่เป็นไปได้ไหมที่จะทำให้คลาสไม่ได้อยู่ในเทมเพลตจากนั้นสร้างฟังก์ชันในคลาสนั้นเป็นเทมเพลต? เช่น:

//I have no idea if this is right, this is just how I think it would look
class Object
{
public:
    template<class T>
    void DoX(){}
};

หรืออะไรบางอย่างในระดับที่ชั้นไม่ได้เป็นส่วนหนึ่งของแม่แบบ แต่ฟังก์ชั่นคืออะไร?

คำตอบ:


115

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


3
และคุณไม่สามารถเชี่ยวชาญได้ :-(
Frank Krueger

7
ไม่จริงอย่างแน่นอน นิยามสามารถอยู่ในไฟล์ cpp ตราบใดที่ถูกเรียกหนึ่งครั้งสำหรับแต่ละพารามิเตอร์เท็มเพลตเฉพาะ n-uplet จากฟังก์ชัน / เมธอดที่ไม่ใช่เท็มเพลตหลังจากที่ถูกกำหนดไว้
Benoît

1
ดังนั้น "ควร" ของฉัน - การเก็บไว้ในส่วนหัวเป็นวิธีที่ง่ายที่สุดเพื่อให้บรรลุ
ไม่แน่ใจ

4
ที่จริงแล้วฉันเชื่อว่าคุณสามารถชำนาญได้อย่างชัดเจน แต่คุณไม่สามารถชำนาญได้เพียงบางส่วน น่าเสียดายที่ฉันไม่รู้ว่านี่เป็นส่วนขยายเฉพาะคอมไพเลอร์หรือมาตรฐาน C ++
Patrick Johnmeyer

7
เป็นมาตรฐาน c ++ คุณสามารถทำโครงสร้าง A {template <typename> void f (); }; แม่แบบ <> โมฆะ A :: f <int> () {} ตัวอย่างเช่น คุณไม่สามารถชำนาญในขอบเขตคลาส แต่คุณสามารถทำได้ดีเมื่อทำในขอบเขตเนมสเปซ (เพื่อไม่ให้สับสนกับขอบเขตที่ความเชี่ยวชาญกำหนดไว้จริง: ความเชี่ยวชาญจะยังคงเป็นสมาชิกของคลาส - แต่คำจำกัดความของมันถูกทำในขอบเขตเนมสเปซบ่อยครั้งขอบเขตที่สิ่งที่ใส่เข้าไปนั้นเหมือนกับขอบเขต บางสิ่งบางอย่างถูกกำหนดที่ - แต่บางครั้งก็ไม่เป็นความจริงเช่นเดียวกับในทุกกรณีของคำจำกัดความนอกคลาส)
โยฮันเนสชอม - litb

70

ดูที่นี่: แม่ , วิธีเทมเพลตสมาชิกแม่แบบสมาชิกฟังก์ชั่นแม่แบบ

class   Vector
{
  int     array[3];

  template <class TVECTOR2> 
  void  eqAdd(TVECTOR2 v2);
};

template <class TVECTOR2>
void    Vector::eqAdd(TVECTOR2 a2)
{
  for (int i(0); i < 3; ++i) array[i] += a2[i];
}

ตัวอย่างที่ดี แต่ทำไมเทมเพลต <typename T> อยู่ในคลาส definitino ... ???
Martian2049

@ Martian2049 ฉันเชื่อว่านี่เป็นเทมเพลตที่ใช้กับฟังก์ชันสมาชิกภายในคลาสเท่านั้นไม่ใช่คลาสทั้งหมด ตรงตามที่ OP ถาม
CBK

21

ใช่ฟังก์ชั่นสมาชิกเทมเพลตนั้นถูกกฎหมายอย่างสมบูรณ์และมีประโยชน์ในหลาย ๆ โอกาส

ข้อแม้เดียวคือฟังก์ชันสมาชิกเทมเพลตไม่สามารถเสมือนได้


9

วิธีที่ง่ายที่สุดคือการวางการประกาศและคำจำกัดความไว้ในไฟล์เดียวกัน แต่อาจทำให้ไฟล์ที่น่าเชื่อถือมีขนาดใหญ่เกินไป เช่น

class Foo
{
public:
template <typename T> void some_method(T t) {//...}
}

นอกจากนี้ยังสามารถใส่นิยามเทมเพลตในไฟล์แยกต่างหากเช่นวางไว้ในไฟล์. cpp และ. h สิ่งที่คุณต้องทำคือการรวมการสร้างอินสแตนซ์ของแม่แบบลงในไฟล์. cpp อย่างชัดเจน เช่น

// .h file
class Foo
{
public:
template <typename T> void some_method(T t);
}

// .cpp file
//...
template <typename T> void Foo::some_method(T t) 
{//...}
//...

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