코드 재사용 및 유형 안전성을 위해 C++ 템플릿을 활용하고 싶지만 API 가장자리에서 템플릿 기반 구현 및 런타임 데이터 기반 외부 인터페이스를 제공합니다. 컴파일러에서 전환 작업을 수행 할 수있는 방법이 있는지 궁금합니다. (즉, 저에게이 작업 중 일부를 수행하십시오.)템플리트가 아닌 공용 API에 대한 템플릿 기반의 개인 구현 구현
이미지에 대해 몇 가지 작업을 수행하려는 고풍스러운 사례를 생각해 봅시다. 다른 색 공간으로 변환하는 것. ,
enum class ImageType : uint8_t {
RGB,
CMYK,
Grayscale
};
그런 다음 우리는 코드를 재사용 할 템플릿 일부 개인 구현을 가지고 :
struct Image { /* Whatever */ };
그런 다음 우리는 우리가 지원하는 변환의 종류의 열거가 : 우리가 어떤 임의의 이미지 클래스가 말 등 :
// Internal implementation
template <ImageType T>
struct ImageConverter {
public:
Image ConvertImage(const Image& img);
private:
void some_shared_code(Image& img) {
// do stuff...
};
};
그런 다음 각 유형별로 몇 가지 메소드 인스턴스가 있습니다. (호출자에게는 모두 동일한 리턴 유형 및 매개 변수 목록을 공유한다는 점에 유의하십시오. 다음
template <> Image ImageConverter<ImageType::RGB>::ConvertImage(const Image& img)
{
Image foo = img;
some_shared_code(foo);
// do other stuff specific to this color space...
return foo;
};
template <> Image ImageConverter<ImageType::CMYK>::ConvertImage(const Image& img)
{
Image foo = img;
some_shared_code(foo);
// do other stuff specific to this color space...
return foo;
};
template <> Image ImageConverter<ImageType::Grayscale>::ConvertImage(const Image& img)
{
Image foo = img;
some_shared_code(foo);
// do other stuff specific to this color space...
return foo;
};
그리고 마지막으로, 우리는이 같은 비 템플릿 API로 외부 세계에이를 팔고 다니다하려면 :
Image ConvertImage(const Image& inImage, ImageType toType) {
switch (toType) {
case ImageType::RGB: {
ImageConverter<ImageType::RGB> ic;
return ic.ConvertImage(inImage);
}
case ImageType::CMYK: {
ImageConverter<ImageType::CMYK> ic;
return ic.ConvertImage(inImage);
}
case ImageType::Grayscale: {
ImageConverter<ImageType::Grayscale> ic;
return ic.ConvertImage(inImage);
}
}
};
을 그리고 그것은 나를 귀찮게 마지막 부분 - 그것은 추한 및 투박한. 가치가있는 부분은 간결성을 위해 non-type 템플릿 매개 변수를 사용하는 인위적인 예제이지만 추상 (템플릿 매개 변수가 유형 인 경우)에 문제가 있습니다.
모든 템플릿 인스턴스가 상속받는 순수 가상 "인터페이스"클래스를 선언하지만 템플릿 인스턴스가 인터페이스 클래스에서 상속되어야합니다. 제 3 자 클래스를 사용하는 경우 가끔 옵션이 아닙니다. (메모리의 레이아웃을 변경하는 것과 같은 다른 단점도 있습니다)
문장의 역할을보다 우아하게 채울 수는 있지만 그 추상적 인 공간에서 작업하는 관용구가 있습니까? 구현 (예 : 템플릿이 아닌 인터페이스 클래스에서 상속)? 이것이 공통적 인 문제 여야하고, 현재 템플릿 -fu의 범위를 벗어나는 영리한 해결책이있을 것 같습니다.
EDIT : 내가 생각하기에 더 많은 것은 아마도 템플릿 기반 메타 프로그래밍 (metaprogramming) 기반의 템플릿이라고 생각하기 시작했다.
struct ImageConverter {
public:
template <typename ConvT>
Image ConvertImage(const Image& img, ConvT conv);
private:
void some_shared_code(Image& img) {
// do stuff...
};
};
그리고 ConvertImage
전문을 :
struct RGBConv{};
struct CMYKConv{};
struct GrayscaleConv{};
그런 다음이 같은 ImageConverter
을 선언 할 수있다) 내 마음에 오는 가능한 해결책의
가독성 관점에서 볼 때 더 우수하지만 API 함수를 템플릿 화해야한다는 것이 문제의 근본적인 점에서 출발합니다. 런타임 데이터와 컴파일 타임 타입을 변환하는 대신, 템플릿으로 템플릿을 푸시했습니다. – ipmcc