여러 클래스에 대한 하나의 템플릿 전문화
-
19-09-2019 - |
문제
템플릿 함수 "foo"가 있다고 가정 해 봅시다.
template<class T>
void foo(T arg)
{ ... }
나는 특정 유형에 대해 전문화 할 수 있습니다.
template<>
void foo(int arg)
{ ... }
모든 내장 숫자 유형 (int, float, double 등)에 동일한 전문화를 사용하고 싶다면 해당 라인을 여러 번 쓸 것입니다. 나는 신체가 다른 기능으로 던져 질 수 있다는 것을 알고 있으며, 단지 모든 전문화의 신체에서 이것을 부르는 것만으로도 만들어야하지만,이 "void foo (...”모든 유형에 대한 글을 쓰지 않으면 더 좋을 것입니다. 이 모든 유형 에이 전문화를 사용하고 싶은 컴파일러를 알릴 가능성이 있습니까?
해결책
당신은 사용할 수 있습니다 std::numeric_limits
유형이 숫자 유형인지 확인하려면 (is_specialized
모든 플로트 및 정수 기본 유형에 맞습니다).
// small utility
template<bool> struct bool2type { };
// numeric
template<typename T>
void fooImpl(T arg, bool2type<true>) {
}
// not numeric
template<typename T>
void fooImpl(T arg, bool2type<false>) {
}
template<class T>
void foo(T arg)
{ fooImpl(arg, bool2type<std::numeric_limits<T>::is_specialized>()); }
다른 팁
사전 처리기와 함께 접근 방식을 사용할 수 있습니다.
foo.inc :
template<>
void foo(TYPE arg)
{ /* do something for int, double, etc. */ }
foo.h :
template<class T>
void foo(T arg)
{ /*do something */ }
#define TYPE int
#include "foo.inc"
#undef TYPE
#define TYPE double
#include "foo.inc"
#undef TYPE
등.
부스트와 함께 :
#include <boost/type_traits/is_scalar.hpp>
#include <iostream>
#include <string>
namespace detail
{
typedef const boost::true_type& true_tag;
typedef const boost::false_type& false_tag;
template <typename T>
void foo(const T& pX, true_tag)
{
std::cout << "special: " << pX << std::endl;
}
template <typename T>
void foo(const T& pX, false_tag)
{
std::cout << "generic: " << pX << std::endl;
}
}
template <typename T>
void foo(const T& pX)
{
detail::foo(pX, boost::is_scalar<T>());
}
int main()
{
std::string s = ":D";
foo(s);
foo(5);
}
부스트없이 대부분 쉽게 할 수 있습니다.
#include <iostream>
#include <string>
// boolean stuff
template <bool B>
struct bool_type {};
typedef bool_type<true> true_type;
typedef bool_type<false> false_type;
// trait stuff
template <typename T>
struct is_scalar : false_type
{
static const bool value = false;
};
#define IS_SCALAR(x) template <> \
struct is_scalar<x> : true_type \
{ \
static const bool value = true; \
};
IS_SCALAR(int)
IS_SCALAR(unsigned)
IS_SCALAR(float)
IS_SCALAR(double)
// and so on
namespace detail
{
typedef const true_type& true_tag;
typedef const false_type& false_tag;
template <typename T>
void foo(const T& pX, true_tag)
{
std::cout << "special: " << pX << std::endl;
}
template <typename T>
void foo(const T& pX, false_tag)
{
std::cout << "generic: " << pX << std::endl;
}
}
template <typename T>
void foo(const T& pX)
{
detail::foo(pX, is_scalar<T>());
}
int main()
{
std::string s = ":D";
foo(s);
foo(5);
}
어쩌면 모든 기본 유형에서 작동하는 기본 템플릿 기능을 정의하고 사용자에게 사용자 정의 유형의 전문화를 위임 할 수 있습니다.
작은 스크립트 (예 : Perl)를 작성하여 소스 파일을 생성 할 수 있습니다. 전문화하려는 모든 유형이 포함 된 배열을 만들고 각각의 함수 헤더를 작성하도록하십시오. MakeFile에 스크립트 실행을 포함시켜 무언가를 변경하면 자동으로 다시 실행할 수도 있습니다.
참고 : 이것은 구현을 가정합니다 foo
예를 들어 각 유형에 대해 사소하고 유사하게 만들 수 있습니다. 그러나 그것은 미래의 관리자가 머리를 긁을 수있는 템플릿/사전 처리기 Mumbo-Jumbo를 피합니다.
요하네스 솔루션의 개선은 다음과 같습니다. 그러나 읽기 쉽습니다. 함수 내부에서 유형을 확인하십시오.
template<typename T>
void foo(T arg)
{
if (numeric_limits<T>::is_specialized) // not a runtime check - compile time constant
{
}
else
{
}
}
유형 특성 사용 (자체 템플릿 전문화)