2016-06-06 2 views
1

나는 다음과 같은 템플릿 기능을 가지고 :템플릿 클래스를 템플릿 함수 전문화에 대한 인수로 사용할 수 있습니까?

예를 들어, 다른 템플릿 함수에 사용 차례에
template <class T> 
inline T ParseValueFromJson(const JSONValue& jsonValue); 

:

template <class T> 
bool TryGetValueFromJson(
    const JSONValue& jsonValue, 
    const String& name, 
    T& variable) 
{ 
    if (!jsonValue.Contains(name)) 
    { 
     return false; 
    } 

    variable = ParseValueFromJson<T>(jsonValue[name]); 
    return true; 
} 

가 지금은 다른 유형의 번호 ParseValueFromJson을 전문으로하는 원하고, 그 중 하나가 템플릿 클래스 (Vector)입니다. 그러나 일반적인 전문성을 사용하여 벡터의 형식 매개 변수가 정의되지 않은 것입니다 의미 :

template <> 
inline Vector<T> ParseValueFromJson<Vector<T>>(const JSONValue& jsonValue) 

게다가 나는 T가 ParseValueFromJson의 버전을 입력 사용하는 것 때문에 내가 T의 유형을 필요 함수 구현하는, 개별 항목을 구문 분석합니다. 따라서이 가능하다, 또는 (I 별도의 TryGetContainerFromJson에 만족해야합니까

template <typename T> 
inline Vector<T> ParseValueFromJson<Vector<T>>(const JSONValue& jsonValue) 

:

내가 전문화에 템플릿 T를 사용하는 경우 물론

, 그것은 모호한 호출 결과 다른 기능입니다 또는 유사한) 함수를 두 번째 템플릿 매개 변수로 템플릿 컬렉션 형식을 걸리는?

답변

4

나는 직렬화 다루는 구현 serializer 템플릿 구조체를 선택할 것이다 (그리고 쉽게 부분적으로 전문화 할 수 있습니다)template function specialization can be troublesome있다.

// Default serializer implementation. 
namespace impl 
{ 
    template <typename T> 
    struct serializer 
    { 
     T from_json(const JSONValue& jv) 
     { 
      // default implementation... 
     } 
    }; 
} 

// Convenient interface function. 
template <class T> 
inline T ParseValueFromJson(const JSONValue& jsonValue) 
{ 
    return impl::serializer<T>{}.from_json(jsonValue); 
} 

// "Special" serializer implementations. 
namespace impl 
{    
    template <typename T> 
    struct serializer<Vector<T>> 
    { 
     Vector<T> from_json(const JSONValue& jv) 
     { 
      Vector<T> result; 
      for(auto c : jv.children()) 
      { 
       result.add(ParseValueFromJson<T>(c)); 
      } 
      return result; 
     } 
    }; 
} 
+0

감사합니다. @ Smeeheey의 해결책에 기대고 있었지만, 아마 재검토하게 될 것입니다. – FlintZA

0

일부 기능을 특수화 할 수는 없지만 다른 템플릿 기능을 포함하여 확실히 오버로드 할 수 있습니다. 이 작품 :

template <class T> 
inline void ParseValueFromJson(const JSONValue& jsonValue, T& output); 

template <class T> 
inline void ParseValueFromJson(const JSONValue& jsonValue, std::vector<T>& output); 

실제로 잘 작동합니다 : 당신이 출력 매개 변수에 의해 돌려 드리겠습니다 경우

귀하의 경우에는
template <typename T> 
void func(const T& arg) 
{ 
    std::cout << "General" << std::endl; 
} 

template <typename T> 
void func(const std::vector<T>& vec) 
{ 
    std::cout << "Vector overload" << std::endl; 
} 

int main() 
{ 
    func(1);     //outputs "General" 
    func(std::vector<int>{1}); //outputs "Vector overload" 

    return 0; 
} 

, 당신은 그래서 당신이 추천 기능을 가지고,이 솔루션을 적용 할 수 코드로, 이미 궁극적으로 출력 매개 변수로 응답을 반환합니다. 통화 사이트에서 그래서, 당신은 단지 당신은 부분적으로 기능 템플릿을 전문으로 할 수

ParseValueFromJson<T>(jsonValue[name], variable); 
+0

또는 태그 반환을 사용하여 값에 의한 반환을 유지할 수 있습니다. – TartanLlama

+0

이 경우 출력 매개 변수를 사용하게되어 매우 기쁩니다. 관심이없는 이유는 이것이 작동하며 반환 값과 비교됩니다. – FlintZA

+0

함수 오버로드는 반환 값 유형에 따라 만 다를 수 없습니다. – Smeeheey

1

(obligatory link to Herb Sutter)에 선

variable = ParseValueFromJson<T>(jsonValue[name]); 

을 변경할 수 있지만, 당신은 항상 기능 템플릿을 오버로드 할 수 있습니다.

template <class > struct tag { }; 

template <class T> 
inline T ParseValueFromJson(const JSONValue& jsonValue) { 
    return impl::ParseValueFromJson(jsonValue, tag<T>{}); 
} 

을 그리고 오버로드의 무리 제공 : 그냥 앞으로 차를 따라, 태그 매개 변수로 유형을 전달하는 기능 전문화에있는 링크에 대한

namespace impl {  
    template <class T> 
    inline T ParseValueFromJson(const JSONValue& jsonValue, tag<T>) { 
     // generic, if that makes sense 
    } 

    template <class T> 
    inline T ParseValueFromJson(const JSONValue& jsonValue, tag<std::vector<T>>) { 
     // vector version 
    } 

    // etc. 
} 
관련 문제