c++ CRTP和递归定义概念

lbsnaicq  于 2023-06-25  发布在  其他
关注(0)|答案(3)|浏览(212)

现在已经有很多问题了(例如:C++ Concepts : CRTP)但答案并没有真正说明如何解决潜在的问题。
我想递归地定义一个概念。大致如下。如果类型是整数,则它对concept_0进行建模。如果一个类型是concept_n元素的范围,则该类型对concept_{n+1}进行建模。我想像下面这样的东西编译

  1. template <typename R>
  2. concept my_object = std::integral<R> || (std::ranges::sized_range<R> && my_object<typename R::value_type>);

有没有办法做到这一点?

knpiaxh1

knpiaxh11#

AFAIK,概念不允许递归。但是模板可以,所以为了让你的例子工作,你可以写一个模板类来建模你的概念,然后把你的概念定义为一个薄薄的 Package 器:

  1. template <typename R>
  2. struct my_object : std::false_type
  3. {};
  4. // specialization for integral types
  5. template <std::integral R>
  6. struct my_object<R>
  7. : public std::true_type
  8. {};
  9. // specialization for ranges using recursion
  10. template <std::ranges::sized_range R>
  11. struct my_object<R>
  12. : public std::conditional_t<
  13. my_object<typename R::value_type>::value,
  14. std::true_type,
  15. std::false_type
  16. >
  17. {};
  18. // wrapping in a concept
  19. template <typename R>
  20. concept my_object_concept = my_object<R>::value;

https://godbolt.org/z/1fqKzrYGh

展开查看全部
wpx232ag

wpx232ag2#

用老式的方法来做:

  1. #include <concepts>
  2. #include <ranges>
  3. #include <vector>
  4. template <typename R>
  5. struct is_my_object
  6. {
  7. static constexpr bool value = false;
  8. };
  9. template <std::integral R>
  10. struct is_my_object<R>
  11. {
  12. static constexpr bool value = true;
  13. };
  14. template <std::ranges::sized_range R>
  15. struct is_my_object<R>
  16. {
  17. static constexpr bool value = is_my_object<typename R::value_type>::value;
  18. };
  19. template <typename R>
  20. concept my_object = is_my_object<R>::value;
  21. static_assert(my_object<int>);
  22. static_assert(!my_object<float>);
  23. static_assert(my_object<std::vector<int>>);
  24. static_assert(my_object<std::vector<std::vector<int>>>);

(This定义将在my_object<int[2]>上失败;解决这个问题很容易)。

展开查看全部
aor9mmx1

aor9mmx13#

你的类型trait实际上并不需要三个模板定义来实现这个概念,因为只有两种情况需要处理。此外,使用std::ranges::range_value_t<R>而不是typename R::value_type还允许您检查C风格的数组类型。

  1. #include <concepts>
  2. #include <ranges>
  3. #include <type_traits>
  4. #include <vector>
  5. template <class R>
  6. struct is_my_object : std::is_integral<R> {};
  7. template <std::ranges::sized_range R>
  8. struct is_my_object<R> : is_my_object<std::ranges::range_value_t<R>> {};
  9. template <class R>
  10. concept my_object = is_my_object<R>::value;
  11. static_assert(my_object<int>);
  12. static_assert(not my_object<float>);
  13. static_assert(my_object<std::vector<int>>);
  14. static_assert(my_object<std::vector<std::vector<int>>>);
  15. static_assert(my_object<int[2]>);
  16. static_assert(not my_object<int[]>);

https://godbolt.org/z/5Krb6cosv

展开查看全部

相关问题