นี่เป็นโอทีเล็กน้อย แต่ฉันคิดว่าจะปล่อยไว้ที่นี่เผื่อว่าจะได้ช่วยคนอื่น ฉันกำลัง googling เกี่ยวกับความเชี่ยวชาญด้านเทมเพลตซึ่งทำให้ฉันมาที่นี่และในขณะที่คำตอบของ @ maxim1000 นั้นถูกต้องและในที่สุดก็ช่วยฉันหาปัญหาได้ แต่ฉันก็ไม่คิดว่ามันจะชัดเจนมากมาย
สถานการณ์ของฉันแตกต่างกันเล็กน้อย (แต่ก็คล้ายกันมากพอที่จะปล่อยให้คำตอบนี้ฉันคิดว่า) มากกว่า OP โดยพื้นฐานแล้วฉันใช้ไลบรารีของบุคคลที่สามกับคลาสทุกประเภทที่กำหนด "ประเภทสถานะ" หัวใจของประเภทเหล่านี้เป็นเพียงแค่enum
s แต่คลาสทั้งหมดสืบทอดมาจากพาเรนต์ทั่วไป (นามธรรม) และมีฟังก์ชันยูทิลิตี้ที่แตกต่างกันเช่นการโอเวอร์โหลดตัวดำเนินการและ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 เล็กน้อย
นี่คือไฟล์ส่วนหัว (ง่ายมาก) สำหรับไฟล์enum
s ในความเป็นจริงแต่ละ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
ชั้นต้องการใช้