2017-09-05 18 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); 
} 

だから私は、シーケンス内のすべてのタイプは、(のは、この例のための反復処理可能なだけで何かを言わせて)「メタタイプ」であることを確認したいです。

コードを単純化できるのであればBoost Hanaを使用しています。

現時点では可能かどうかわからない。私はそれがほしいと思う、私はちょうどより多くのメタプログラミングのものを学ぶ必要があると思う。だから私は引き続き検索して試してみるだろうが、誰かが既に答えを持っているなら、ありがとう!

+1

質問:あなたは 'T tuple'をどのように使用しますか?それにはどんな制約がありますか?それは 'std :: tuple'でなければなりませんか? 'std :: tuple_element'は' std :: tuple_element'を使用します。独自の特性や制約を定義していない場合は... 'std :: tuple_element'も' std :: array'と 'std :: pair'を処理することに注意してください。 'T'も' foo'を使うように特化することを期待しています。それ以外の場合は 'decltype(std :: get (タプル))'を試してみても構いませんが、タプル要素にアクセスすることもできます。 – BeyelerStudios

+0

あなたは明らかに、現在のバージョンのコンセプトを使用していません。私が知る限り、コンセプトのバージョンでは、「コンセプトブール」はなくなっています。あなたは特にどのバージョンをお求めですか? – Yakk

+0

@Yakkまあ、私はhttp://en.cppreference.com/w/cpp/language/constraintsを読んでいて、Gcc 7.1を使っているので、最後のものになると思っていました。 –

答えて

3

概念ので、あなたはからいくつかの「メタプログラミングのヘルプ」を必要とするこれを行うには、設計によってメタプログラミングを行うためには弱すぎます残りの言語。私は、テンプレートとその型パラメータへのタイプを分解するテンプレートの特殊化を使用して、満足させるために、これらのパラメータのすべてを必要とする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

コンセプトブールはまだTSに入っていますか? (OPの前のコメントのために尋ねる) –

+3

@jasonrice TSは公開されており、基本的には最終的なので、はい。しかし、C++ 20ワーキングペーパーにはありませんが、'です。 Wg21はトロントの概念構文から "ブール"を削除しました。 – Casey

1

tupleがタイプ名typeを定義するタイプしか保持していないかどうかを確認する方法の例を次に示します。ここでのトリックは、タプルstd::tuple<T0, ..., TN, TM>の新しいタイプstd::pair<std::pair<...std::pair<void, T0>, ...TN>, TM>を定義するタプルタイプを定義することです。これはworks in GCC 7.2です。私は、参照を見つけられなかったので、バリデーションの制約をどのようにもっときれいに組み合わせるかに興味があります。

#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::Searchablehana::Foldableあるhana::Sequenceにすることができることに留意すべきです。ここで

hana::Searchableとして使用std::tupleと例です。

#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