2017-09-05 125 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元組?你有什麼限制嗎?它必須是一個'std :: tuple'?如果是這樣,使用'std :: tuple_element',如果沒有定義你自己的特徵和約束...注意'std :: tuple_element'也處理'std :: array'和'std :: pair',所以也許你可以期望任何'T'專門化它以及使用'foo'。否則,你可能想嘗試使用'decltype(std :: get (tuple))'或者你訪問你的元組元素。 – 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

「concept 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。我會感興趣的是如何更乾淨地結合可變參數限制,因爲我沒有找到任何參考。

#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

這裏是std::tuple一個例子作爲hana::Searchable

#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