【问题标题】:How to write a c++ concept for class with member function template that takes a template argument?如何使用带有模板参数的成员函数模板为类编写 C++ 概念?
【发布时间】:2021-02-21 02:33:55
【问题描述】:

我如何编写需要一个成员函数模板的 C++ 20 概念,该模板接受一个必须提供的模板参数?

以下概念的目标是检查一个类型是否类似于元组,除了检查std::get<I>(t),我想检查t.get<I>()

以下内容不能使用开关-std=c++2a 与 g++ 10.1 一起编译。

#include <concepts>

template <typename E> 
concept Tpl = requires(E const e, int idx)
   {
      {
         e.template get<idx>()
      } -> std::convertible_to<float>;
   };

如果template没有在get之前使用,当然是不能编译的(没有尖括号,小于/大于运算符)。

【问题讨论】:

  • 我不确定你在这里问什么 - 你所说的“明确陈述的参数类型(注意可推导)”是什么意思?我们在这里讨论的是哪个论点?
  • 我假设他想要一些 Tuple-Like 类,它的成员函数的行为类似于 std::get&lt;Idx&gt;(TupleLike) - 但就像成员函数一样。
  • @Bernd 如果这就是 OP 想要的,那么 OP 可以编辑问题来说明这一点。或者如果他们想要不同的东西,他们应该说不同的东西。
  • 是的,就像在 std::tuple 中一样。由于成员函数没有参数,因此不能推导出成员函数模板参数。这是设计使然,模板参数在调用中声明:e.get&lt;idx&gt;() 在模板调用中,e.template get&lt;idx&gt;()
  • 是一个参数化的整数吗?检查e.template get&lt;(int)0&gt;() 的有效性还不够吗?

标签: c++ templates member c++20 concept


【解决方案1】:

这个:

template <typename E> 
concept Tpl = requires(E const e, int idx)
   {
      {
         e.template get<idx>()
      } -> std::convertible_to<float>;
   };

不起作用,因为idx 不是常量表达式,在调用get 的上下文中您需要它是一个。

为此,您需要选择索引的特定值以进行检查。你唯一可以选择的是0

template <typename E> 
concept Tpl = requires (E const e) {
    { e.template get<0>() } -> std::convertible_to<float>;
};

这可能会匹配一个函数模板get,它的模板参数类型为int*nullptr_t。如果这是一个问题,我们可以用更复杂的方式拼写 0 以避免它成为空指针常量,无论是简单的 1-1 还是将 integral_constant&lt;size_t, 0&gt; 类型的对象作为第二个“参数”:

template <typename E> 
concept Tpl = requires (E const e, std::integral_constant<size_t, 0> value) {
    { e.template get<value()>() } -> std::convertible_to<float>;
};

如果最终目标是检查e.get&lt;I&gt;() 是否适用于所有 I[0, tuple_size_v&lt;E&gt;),那么您将不得不以不同的方式处理此问题。在这种情况下,您会希望您检查的索引成为概念本身的一部分。如:

template <typename E, size_t I>
concept tuple_like_impl = requires (E const e) {
    { e.template get<I>() } -> std::convertible_to<float>;
};

然后构建一个Is... 的参数包,以便最终构建一个类似(tuple_like_impl&lt;E, Is&gt; &amp;&amp; ...) 的约束。

但这是你应该采取的步骤,只有当你确实需要时。

【讨论】:

    【解决方案2】:

    要让它编译,你可以这样写:

    template <typename E, int idx> 
    concept Tpl = requires(E const e)
       {
          {
             e.template get<idx>()
          } -> std::convertible_to<float>;
       };
    

    但是告诉我们你真正想要什么。

    【讨论】:

    • 虽然您的猜测可能是合理的,甚至在某些情况下会更正,但您应该在回答问题之前尝试弄清 OP 的含义。
    • 感谢您的回复 - 我同意。
    • 我不想将idx添加到类模板参数中,而是添加到函数中。背景:它是多向量表达式(表达式模板)概念的简化示例,其中每个表达式应提供类似于元组中的系数访问,但稀疏。返回值类型随索引而变化,以允许区分编译时常量(转换为值的特殊类实例)或运行时计算的值。计算值。
    猜你喜欢
    • 2018-12-28
    • 2019-11-23
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多