นี่เป็นโอทีเล็กน้อย แต่ฉันคิดว่าจะปล่อยไว้ที่นี่เผื่อว่าจะได้ช่วยคนอื่น ฉันกำลัง googling เกี่ยวกับความเชี่ยวชาญด้านเทมเพลตซึ่งทำให้ฉันมาที่นี่และในขณะที่คำตอบของ @ maxim1000 นั้นถูกต้องและในที่สุดก็ช่วยฉันหาปัญหาได้ แต่ฉันก็ไม่คิดว่ามันจะชัดเจนมากมาย
สถานการณ์ของฉันแตกต่างกันเล็กน้อย (แต่ก็คล้ายกันมากพอที่จะปล่อยให้คำตอบนี้ฉันคิดว่า) มากกว่า OP โดยพื้นฐานแล้วฉันใช้ไลบรารีของบุคคลที่สามกับคลาสทุกประเภทที่กำหนด "ประเภทสถานะ" หัวใจของประเภทเหล่านี้เป็นเพียงแค่enums แต่คลาสทั้งหมดสืบทอดมาจากพาเรนต์ทั่วไป (นามธรรม) และมีฟังก์ชันยูทิลิตี้ที่แตกต่างกันเช่นการโอเวอร์โหลดตัวดำเนินการและstatic toString(enum type)ฟังก์ชัน แต่ละสถานะenumแตกต่างกันและไม่เกี่ยวข้องกัน ตัวอย่างเช่นหนึ่งenumมีฟิลด์NORMAL, DEGRADED, INOPERABLEอื่นมีAVAILBLE, PENDING, MISSINGฯลฯ ซอฟต์แวร์ของฉันรับผิดชอบในการจัดการสถานะประเภทต่างๆสำหรับส่วนประกอบต่างๆ มันเกี่ยวกับว่าฉันต้องการใช้toStringฟังก์ชันเหล่านี้enumชั้นเรียน แต่เนื่องจากเป็นนามธรรมฉันจึงไม่สามารถสร้างอินสแตนซ์ได้โดยตรง ฉันสามารถขยายแต่ละชั้นเรียนที่ฉันต้องการใช้ แต่ในที่สุดฉันก็ตัดสินใจที่จะสร้างtemplateชั้นเรียนซึ่งtypenameจะเป็นสถานะที่เป็นรูปธรรมที่enumฉันสนใจ อาจมีการถกเถียงกันบ้างเกี่ยวกับการตัดสินใจนั้น แต่ฉันรู้สึกว่ามันได้ผลน้อยกว่าการขยายenumคลาสนามธรรมแต่ละคลาสด้วยตัวของฉันเองและใช้ฟังก์ชันนามธรรม และแน่นอนในรหัสของฉันฉันแค่อยากจะสามารถเรียก.toString(enum type)และให้มันพิมพ์การแสดงสตริงของสิ่งenumนั้น เนื่องจากทุกenumอย่างไม่เกี่ยวข้องกันเลยต่างคนต่างมีของตัวเองtoStringฟังก์ชันที่ (หลังจากการวิจัยบางอย่างที่ฉันเรียนรู้) ต้องถูกเรียกโดยใช้ความเชี่ยวชาญพิเศษของเทมเพลต นั่นทำให้ฉันมาที่นี่ ด้านล่างนี้เป็น MCVE ของสิ่งที่ฉันต้องทำเพื่อให้งานนี้ถูกต้อง และจริงๆแล้วคำตอบของฉันแตกต่างจาก @ maxim1000 เล็กน้อย
นี่คือไฟล์ส่วนหัว (ง่ายมาก) สำหรับไฟล์enums ในความเป็นจริงแต่ละenumคลาสถูกกำหนดไว้ในไฟล์ของตัวเอง ไฟล์นี้แสดงถึงไฟล์ส่วนหัวที่ให้มาเป็นส่วนหนึ่งของไลบรารีที่ฉันใช้:
#include <string>
class Enum1
{
public:
enum EnumerationItem
{
BEARS1,
BEARS2,
BEARS3
};
static std::string toString(EnumerationItem e)
{
}
};
class Enum2
{
public:
enum EnumerationItem
{
TIGERS1,
TIGERS2,
TIGERS3
};
static std::string toString(EnumerationItem e)
{
}
};
เพิ่มบรรทัดนี้เพื่อแยกไฟล์ถัดไปเป็นบล็อกรหัสอื่น:
#include <string>
template <typename T>
class TemplateExample
{
public:
TemplateExample(T t);
virtual ~TemplateExample();
std::string toString();
private:
T type_;
};
template <typename T>
TemplateExample<T>::TemplateExample(T t)
: type_(t)
{
}
template <typename T>
TemplateExample<T>::~TemplateExample()
{
}
ไฟล์ถัดไป
#include <string>
#include "enums.h"
#include "TemplateExample.h"
template <>
std::string TemplateExample<Enum1::EnumerationItem>::toString()
{
return Enum1::toString(type_);
}
template <>
std::string TemplateExample<Enum2::EnumerationItem>::toString()
{
return Enum2::toString(type_);
}
ไฟล์ถัดไป
#include <iostream>
#include "TemplateExample.h"
#include "enums.h"
int main()
{
TemplateExample<Enum1::EnumerationItem> t1(Enum1::EnumerationItem::BEARS1);
TemplateExample<Enum2::EnumerationItem> t2(Enum2::EnumerationItem::TIGERS3);
std::cout << t1.toString() << std::endl;
std::cout << t2.toString() << std::endl;
return 0;
}
และผลลัพธ์นี้:
BEARS1
TIGERS3
ไม่มีเงื่อนงำหากนี่เป็นทางออกที่ดีในการแก้ปัญหาของฉัน แต่มันใช้ได้ผลสำหรับฉัน ตอนนี้ไม่ว่าฉันจะใช้การแจงนับกี่ประเภทสิ่งที่ฉันต้องทำคือเพิ่มสองสามบรรทัดสำหรับtoStringวิธีการในไฟล์. cpp และฉันสามารถใช้toStringวิธีการที่กำหนดไว้แล้วของไลบรารีโดยไม่ต้องใช้งานด้วยตัวเองและไม่ต้องขยายแต่ละรายการenumชั้นต้องการใช้