2017-09-05 126 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