2017-09-05 8 views
2

튜플에 "메타 유형"만 포함되어 있는지 컴파일러에게 확인하고 싶습니다.C++ 개념 루프

나는 완전히 C++ 개념에 대해 새로운 사람입니다.

template < typename T > 
struct Type { 
    using type = T; 
}; 

//! A type can be easily check with a small concept 
template < typename T > 
concept bool C_Type = requires { 
    typename T::type; 
}; 

//! But how to apply it on a whole tuple? 
template < typename T > 
void foo(T tuple) {} 

int main() { 

    constexpr auto test = std::make_tuple(Type<int>{}, Type<double>{}); 
    foo(test); 
} 

그래서 나는 순서 내부의 모든 유형이 "메타 형"이다 (의이 예제 만 뭔가의 Iterable 말을하자) 있는지 확인하고 싶습니다.

코드를 단순화 할 수 있다면 Boost Hana를 사용하고 있습니다.

현재 가능한지 확실하지 않습니다. 나는 그것이 더 많은 메타 프로그래밍을 배워야한다고 생각한다. 그래서 나는 계속해서 검색하고 시도 할 것이지만 누군가가 이미 답을 가지고 있다면, 고마워!

+1

질문 : 당신은'T tuple'을 어떻게 사용하겠습니까? 당신은 그것에 어떤 제약을 두는가? 'std :: tuple'이어야합니까? 그렇다면'std :: tuple_element'을 사용하십시오. 자신의 특성과 제약을 정의하지 않으면 ...'std :: tuple_element'도'std :: array'와'std :: pair'를 처리합니다. 어떤'T'도'foo'를 사용하는 것을 전문으로 할 것을 기대하십시오. 그렇지 않으면'decltype (std :: get (tuple))'을 사용하거나 튜플 요소에 액세스 할 수 있습니다. – BeyelerStudios

+0

개념의 현재 버전은 분명히 사용하고 있지 않습니다. 왜냐하면 '개념 bool'은 내가 아는 한 개념의 버전에서 사라 졌기 때문입니다. 어떤 버전에 대해 구체적으로 묻고 있습니까? – Yakk

+0

@Yakk 글쎄, 나는 http://en.cppreference.com/w/cpp/language/constraints를 읽고 Gcc 7.1을 사용하고 있기 때문에 마지막에있을 생각이었다. –

답변

3

개념은 그래서 당신이 일부 "메타 프로그래밍의 도움을"필요 이렇게, 메타 프로그래밍을 수행하기에 너무 약한 디자인에 있습니다 : 여기

hana::Searchable으로 사용 std::tuple와 예입니다 나머지 언어. 나는 템플릿과 형식 매개 변수로 유형을 분해하는 템플릿 특수화를 사용하고 만족하는 모든 매개 변수를 필요로 C_Type :

template <class> 
constexpr bool TypeTuple_ = false; 
template <template <class...> class Tuple, class... Types> 
    requires (C_Type<Types> && ...) 
constexpr bool TypeTuple_<Tuple<Types...>> = true; 

template <class T> 
concept bool TypeTuple = TypeTuple_<T>; 

hana::tuple으로 작동하고, std::tuple - 모든 유형의 매개 변수를 어떤 템플릿 .

+1

'개념 bool '은 여전히 ​​TS에 있습니까? (OP에 대한 이전 코멘트로 인해 묻습니다) –

+3

@jasonrice TS가 게시되었으며 기본적으로 최종입니다. 그러나 '은 C++ 20 작업 보고서에 포함되어 있지 않습니다. Wg21은 토론토의 개념 구문에서 "bool"을 제거했습니다. – Casey

1

다음은 tuple이 유형 이름 type을 정의하는 유형 만 보유하고 있는지 확인할 수있는 방법의 예입니다. 여기의 트릭은 튜플 std::tuple<T0, ..., TN, TM>에 대해 새로운 유형 std::pair<std::pair<...std::pair<void, T0>, ...TN>, TM>을 정의하는 튜플 유형을 정의하는 것입니다. 이 works in GCC 7.2입니다. 나는 하나의 참조를 찾지 못했을 때 variadic 제약을 어떻게 더 깔끔하게 결합하는지에 관심을 가질 것이다.

#include <array> 
#include <tuple> 

template<typename T> 
struct Type { 
    using type = T; 
}; 

template<typename Tuple, size_t I = std::tuple_size<Tuple>::value> 
struct TupleType { 
    using type = std::pair<typename TupleType<Tuple, I - 1>::type, 
          typename std::tuple_element<I - 1, Tuple>::type>; 
}; 

template<typename Tuple> 
struct TupleType<Tuple, 0> { 
    using type = void; 
}; 

template<typename T> 
concept bool C_TupleType = requires { 
    typename TupleType<T>::type; 
}; 

void foo(C_TupleType tuple) { } 

int main() { 
    constexpr auto test = std::make_tuple(Type<int>{}, Type<double>{}); 
    foo(test); 

    // also works on pair and array 
    constexpr auto test1 = std::make_pair(Type<int>{}, Type<double>{}); 
    foo(test1); 
    constexpr std::array<Type<int>, 3> test2; 
    foo(test2); 

    // and of course TupleType is also a meta type 
    constexpr std::array<TupleType<std::pair<int, int>>, 13> test3; 
    foo(test3); 

    return 0; 
} 
2

저는 개념에 너무 익숙하지 않지만 Boost.Hana를 사용하여 여러 가지면에서 분명히이를 달성 할 수 있습니다.

튜플 유형은 hana::Sequence으로 만들 수 있으며, 이는 일반적으로 hana::Searchablehana::Foldable이기도합니다.

#include <boost/hana.hpp> 
#include <boost/hana/ext/std/tuple.hpp> 
#include <tuple> 
namespace hana = boost::hana; 

template < typename T > 
concept bool C_Type = requires { 
    typename T::type; 
}; 

auto is_C_Type = hana::overload_linearly([](C_Type const&) { return hana::true_c; }, 
             [](auto const&) { return hana::false_c; }); 

template < typename T > 
constexpr bool foo(T const& tuple) { 
    return hana::all_of(tuple, is_C_Type); 
} 

int main() { 
    constexpr auto test = std::tuple{hana::type_c<int>, hana::type_c<double>}; 
    static_assert(foo(test)); 
} 

https://wandbox.org/permlink/YNZDX7uN6mgUdmje