C++ 概念循环
C++ concepts loop
我想请编译器检查一个元组是否只包含 "meta types"。
顺便说一句,我对 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);
}
所以我想确保序列中的每个类型(在这个例子中我们只说一些可迭代的)是 "meta type"。
如果可以简化代码,我正在使用 Boost Hana。
目前我什至不确定这是否可能。我希望是这样,我想我只需要学习更多元编程的东西。所以我会继续搜索和尝试,但如果有人已经有了答案,谢谢!
这是一个示例,说明如何检查 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;
}
我不太熟悉概念,但是您当然可以通过 Boost.Hana 以多种方式实现这一点。
从注释中可以看出,任何元组类型都可以制成 hana::Sequence
,按照惯例也是 hana::Searchable
和 hana::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));
}
概念在设计上太弱而无法执行元编程,因此要做到这一点,您需要 "metaprogramming help" 来自其他语言的一些知识。我会使用模板特化将类型分解为模板及其类型参数,然后要求所有这些参数满足 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
- 任何采用所有类型参数的模板。
我想请编译器检查一个元组是否只包含 "meta types"。
顺便说一句,我对 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);
}
所以我想确保序列中的每个类型(在这个例子中我们只说一些可迭代的)是 "meta type"。
如果可以简化代码,我正在使用 Boost Hana。
目前我什至不确定这是否可能。我希望是这样,我想我只需要学习更多元编程的东西。所以我会继续搜索和尝试,但如果有人已经有了答案,谢谢!
这是一个示例,说明如何检查 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;
}
我不太熟悉概念,但是您当然可以通过 Boost.Hana 以多种方式实现这一点。
从注释中可以看出,任何元组类型都可以制成 hana::Sequence
,按照惯例也是 hana::Searchable
和 hana::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));
}
概念在设计上太弱而无法执行元编程,因此要做到这一点,您需要 "metaprogramming help" 来自其他语言的一些知识。我会使用模板特化将类型分解为模板及其类型参数,然后要求所有这些参数满足 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
- 任何采用所有类型参数的模板。