2016-11-16 7 views
0

기본적으로, 벡터 (유형) 매개 변수와 비 벡터 유형 매개 변수에 대해 함수가 다르게 동작하도록하려고합니다.C++ 벡터 <T>을 사용하여 템플릿을 특수화하는 방법은 무엇입니까?

#include <vector> 
using namespace std; 

template <typename type> 
struct is_vector { 
    static const bool value = false; 
}; 

template <typename type> 
struct is_vector<vector<type>> 
{ 
    static const bool value = true; 
}; 
template <typename type> 
type read() 
{ 
    if (is_vector<type>::value) 
    {  
     type vec(10); 
     vec.front()=1;//left of '.front' must have class/struct/union 
     return vec; 
    } 
    else 
    { 
     return{}; 
    } 
} 
int main() 
{ 
    auto i= read<int>(); 
} 

벡터를 typename으로 사용하면서 벡터를 반환하려면 int를 typename으로 사용하면서 int를 반환하십시오.

그러나 is_vector (int) :: value가 false를 반환하므로 내 컴파일러에서 "left of '.front'에 class/struct/union이 있어야한다고보고하는 이유는 무엇입니까?

내가 원하는 것은 문자열을 벡터 (형식) 또는 벡터 (벡터 (형식))로 올바르게 deserialize하는 것입니다.

multidemonsional 벡터를 템플릿 매개 변수로 전달하면서 재귀 적으로 read 함수를 호출해야하지만 컴파일러에서이를 수행하지 않아도됩니다.

template <typename type> 
struct is_vector { 
    static const bool value = false; 
}; 

template <typename type> 
struct is_vector<vector<type>> 
{ 
    static const bool value = true; 
}; 

template <typename type> 
type read(char*& str) 
{ 
    if (is_vector<type>::value) 
    {  
     type vec(read<uint8_t>(str)); 
     for (auto& e : vec) 
      e = read<type::value_type>(str); 
     return vec; 
    } 
    return *reinterpret_cast<type*>((str += sizeof(type)) - sizeof(type)); 
} 

그래서 전문성을 시험해 보았습니다.

template<> 
vector<int> read<vector<int>>(char*& str) 
{ 
    vector<int> vec(read<uint8_t>(str)); 
    for (auto& e : vec) 
     e = read<int>(str); 
    return vec; 
}//works 

template <typename type> 
template <> 
vector<type> read<vector<type>>(char*& str) 
{ 
    vector<type> vec(read<uint8_t>(str)); 
    for (auto& e : vec) 
     e = read<type>(str); 
    return vec; 
}//don't work 

내가 사용하는 모든 유형의 읽기 기능을 실제로 수동으로 다시 작성해야합니까?

가 (벡터 같은 (벡터 (벡터 (INT)))?)

+0

는 벡터 수표는 * 런 인 시간 * 확인. 해당 분기의 모든 코드는 여전히 컴파일 가능해야합니다. –

+0

첫 번째 : 'is_vector'조건자는 컴파일시 평가됩니다. if에서이를 사용하면 어떤 템플릿을 사용해야하는지 완전히 이해하지 못했다는 것을 나타냅니다. – Albjenow

+0

@Albjenow 메타 프로그래밍에 대해 잘 모릅니다. 어떻게 벡터와 팟 유형에 대해 다른 코드를 생성 할 수 있습니까? – iouvxz

답변

2

당신은 반환 형식 R 적어도 매개 변수가있는 함수 템플릿 foo<R>을 원하고, 당신이 전문 구현을 원하는 때 R = std::vector<U> 임의의 유형 U에 대해

foo<R>의 인수가 무엇이 될지는 중요하지 않으므로 그림 은 없다고 가정합니다. 다음과 같이

특성 템플릿을 정의 : : 여기에 당신이 그렇게 할 방법이와

template<typename T> 
struct is_vector 
{ 
    static constexpr bool value = false; 
}; 

template<template<typename...> class C, typename U> 
struct is_vector<C<U>> 
{ 
    static constexpr bool value = 
     std::is_same<C<U>,std::vector<U>>::value; 
}; 

,

is_vector<T>::value 

는 컴파일 타임에 true가됩니다에 대한, 경우에만, T = std::vector<U> 일부 U.

그런 다음 줄에 foo<R>() 두 오버로드를 정의

template <typename R> 
std::enable_if_t<!is_vector<R>::value,R> foo() 
{ 
    // Your non-vector implementation instead of... 
    std::cout << 
     "In non-vector specialization of `foo<R>()`\n"; 
    return R(); 
} 

template <typename R> 
std::enable_if_t<is_vector<R>::value,R> foo() 
{ 
    // Your vector implementation instead of... 
    std::cout << 
     "In vector specialization of `foo<R>()`\n"; 
    return R(); 
} 

이 두 오버로드는 상호 배타적 공동 철저한이다. 첫 번째 과부하는 is_vector<R>::value이 거짓 일 때만 합법적 코드가됩니다. 두 번째 오버로드는 is_vector<R>::value이 true 인 경우에만 합법적 인 코드가됩니다. std::enable_if, 의 행동 덕분에 연구하고 이해해야합니다.

컴파일러는 이러한 템플릿은 코드에서 발견 한 몇 가지 전화 foo<type>()을 구현하기 위해 오버로드 하나를 선택해야

, 그것은 type이 템플릿 매개 변수에 연결하면 오버로드 의 단 하나조차 컴파일되지 않습니다 것을 발견 R. type 일부 std::vector<U>하고 type하지 일부 std::vector<U>경우 두 번째 컴파일하지 않을 경우 첫 번째는 컴파일되지 않습니다. 유익하게도 컴파일러는 컴파일 할 수있는 것을 선택합니다. 그건 SFINAE ("Substitution Failure Is Not An Error"), 이라고하며 문제의 해결책입니다.

여기 예시 프로그램 :

#include <vector> 
#include <type_traits> 
#include <iostream> 

template<typename T> 
struct is_vector 
{ 
    static constexpr bool value = false; 
}; 

template<template<typename...> class C, typename U> 
struct is_vector<C<U>> 
{ 
    static constexpr bool value = 
     std::is_same<C<U>,std::vector<U>>::value; 
}; 

template <typename R> 
std::enable_if_t<!is_vector<R>::value,R> foo() 
{ 
    // Your non-vector implementation instead of... 
    std::cout << 
     "In non-vector specialization of `foo<R>()`\n"; 
    return R(); 
} 

template <typename R> 
std::enable_if_t<is_vector<R>::value,R> foo() 
{ 
    // Your vector implementation instead of... 
    std::cout << 
     "In vector specialization of `foo<R>()`\n"; 
    return R(); 
} 

int main() 
{ 
    auto i = foo<int>(); 
    (void)i; 
    auto vc = foo<std::vector<char>>(); 
    (void)vc; 
    return 0; 
} 

하는 출력 :

In non-vector specialization of `foo<R>()` 
In vector specialization of `foo<R>()` 

(GCC 6.1/연타 3.8 -std=c++14see live)을