2017-05-04 1 views
3

C++ 17은 형식이 아닌 템플릿 매개 변수에 대해 auto 키워드를 제공합니다. 이를 템플릿 템플릿 매개 변수와 결합하여 템플릿 변수와 함께 인수로 사용할 수 있습니까?템플릿 변수를 템플릿 매개 변수로 사용할 수 있습니까 (클래스 템플릿과 유사)?

template <template <typename> auto X> // <-- This seems to be illegal 
struct Foo 
{ 
}; 

배경 : 나는 type_vector 클래스에 대한 copy_if을 구현하려는
. 나는 값이 템플릿 구조체에 내 모든 변수를 포장 할 수 물론

template <typename Container, 
      template <typename> auto Condition> // If this were allowed 
struct copy_if; 

template <typename... Ts, 
      template <typename> auto Condition> 
struct copy_if<type_vector<Ts...>, Condition> 
{ 
    using type = decltype(
     (type_vector<>{} + ... + 
      std::conditional_t<Condition<Ts>, 
          type_vector<Ts>, 
          type_vector<>>{})); 
}; 

,하지만 난 차라리 : 내가 사용하고자하는 모든 조건이 템플릿 변수로 사용할 수 있기 때문에, 한 가지 방법이 될 것이다 구현 그것을 피하십시오.

+0

당신이 type_vector을 정의? –

+0

@RichardHodges 예,'type_vector'가 정의되어 있습니다. 두 개의'type_vector'를 연결하기 위해'operator +'와 같습니다. – Rumburak

+0

C++ 17을 잘 모릅니다. 그러나'template auto'는 의미가 없습니다. 자동은 단지 클래스 일 수 있기 때문입니다. 예 : '템플릿 int'의 개념이 없습니다 –

답변

1

매개 변수가 변수 템플리트에 맞으면 추가 술어 매개 변수 (constexpr lambda available since C++ 17)가 충분합니까?

#include <algorithm> 
#include <iostream> 
#include <string> 
#include <type_traits> 

template <class T> 
constexpr bool condition = true; 

template <> 
constexpr bool condition<int> = false; 


template <class T> 
struct tag { 
    using type = T; 
}; 

template <class... Ts> 
struct type_vector { 
    template <class... Ts2> 
    type_vector<Ts..., Ts2...> operator+(type_vector<Ts2...>); 
}; 

template <class... Ts, 
      class Predicate> 
auto copy_if(type_vector<Ts...>, Predicate p) 
{ 
    return decltype(
     (type_vector<>{} + ... + 
      std::conditional_t<p(tag<Ts>{}), 
          type_vector<Ts>, 
          type_vector<>>{})){}; 
}; 

int main() { 
    auto predicate = [](auto x){ return condition<typename decltype(x)::type>;}; 
    std::cout << typeid(decltype(copy_if(type_vector<int, float, double>{}, predicate))).name() << std::endl; 
} 

C++ filt을 출력 :

type_vector<float, double> 

[live demo]


이 편집 : 매개 변수 유형을 파견 인공 태그를 사용할 때

이 상황에있다가 인식 될 수있다 성가신 일이다. 당신이 그것을 피하고 싶다면 또 다른 방법이 있습니다. 이 사람은 실제로 단지 (중 std::true_type 또는 std::false_type의 동일해야) 결과 유형을 평가하기 위해 인스턴스화 람다의 operator() 템플릿을 호출 피한다 :

#include <algorithm> 
#include <iostream> 
#include <string> 
#include <type_traits> 

template <class T> 
constexpr bool condition = true; 

template <> 
constexpr bool condition<int> = false; 

template <class... Ts> 
struct type_vector { 
    template <class... Ts2> 
    type_vector<Ts..., Ts2...> operator+(type_vector<Ts2...>); 
}; 

template <class... Ts, 
      class Predicate> 
auto copy_if(type_vector<Ts...>, Predicate p) 
{ 
    return decltype(
     (type_vector<>{} + ... + 
      std::conditional_t<decltype(p(std::declval<Ts>())){}, 
          type_vector<Ts>, 
          type_vector<>>{})){}; 
}; 

int main() { 
    auto predicate = [](auto x){ return std::integral_constant<bool, condition<decltype(x)>>{};}; 
    std::cout << typeid(decltype(copy_if(type_vector<int, float, double>{}, predicate))).name() << std::endl; 
} 

[live demo]

+0

니스! 나는 일반적인 람다 (lambda)를 사용하려고 생각했지만'tag' 클래스는 생각하지 않았습니다. 그러나'copy_if '를 사용하고자하는 사람은 T. – Rumburak

+0

대신''태그를 처리해야합니다. 예, 약간 직관력이 떨어질 수 있습니다. 나는이 접근법에 대해 좀 더 생각하려고 노력할 것입니다. 아마도 다른 것이 내 마음에 올 것입니다. –

+0

감사합니다. 아마도 템플릿 사이트를 작성하게 될 것입니다. 그 이유는 호출 사이트에서 쉽게 벗어날 수 있기 때문입니다.하지만 두 번째 솔루션은 좋은 대안입니다. – Rumburak

관련 문제