【问题标题】:Is there a C++20 way to detect if a type is an instantiation of a template using just concepts and requires()?是否有 C++20 方法来检测类型是否是仅使用概念和 requires() 的模板的实例化?
【发布时间】:2021-04-28 16:34:37
【问题描述】:

多年来,我一直使用以下代码来检测任意类型是否为模板实例化:

namespace priv {
    template <typename, template <typename...> typename>
    struct _is_instance_impl : public std::false_type {};

    template <template <typename...> typename U, typename...Ts>
    struct _is_instance_impl<U<Ts...>, U> : public std::true_type {};
}

template <typename T, template <typename ...> typename U>
using is_instance = priv::_is_instance_impl<std::decay_t<T>, U>;

这也适用于 C++20 概念:

template <typename T, template <typename ...> typename U>
concept instance_of = priv::_is_instance_impl<std::decay_t<T>, U>::value;

template <typename T>
std::size_t len_of(T &&s) requires instance_of<T, std::basic_string> {
        return s.length();
}

我试图用 C++20 requires() 表达式替换这个基于 SFINAE 的代码,但没有成功。

如果真的可能的话,有没有人知道如何实现这一点?

【问题讨论】:

  • 我认为instance_of 有时可能会出现问题。例如,std::vector&lt;bool&gt;std::vector 的一个实例,所以...
  • “我试图用 C++20 的 requires() 表达式替换这个基于 SFINAE 的代码” - 没有关于该代码的“基于 SFINAE”的内容,requires 表达式会非常无论如何都要“基于SFINAE”。您当前的方法没有什么“不好”的地方需要更换。
  • @Barry 是的,我的错。我找不到令人满意的方式来描述可以被称为“我们在概念之前都使用过的东西”,所以我写了这个,却没有意识到requires 确实仍然是 SFINAE。我问这个问题主要是因为,尽管我知道旧的方法仍然很好,但我很好奇是否有更新的方法来实现同样的效果,也许比这更“神秘”(尽管我很习惯阅读那些如今的 SFINAE 咒语......)。
  • @mcilloni:根据我的经验,大多数时候有人想问一个类型是否是某个模板的实例,而他们真正想要的是更一般的东西。例如,如果你有一个函数要限制在 vector 上,那么将它限制在 contiguous_range 上可能更合理,从而允许更多类型。

标签: c++ c++20 sfinae c++-concepts


【解决方案1】:

没有助手,我成功得到的最接近的是:

template <class T, template <typename...> class C>
concept test = requires (T t)
{
    {[] <typename... Ts>(C<Ts...>& c) -> C<Ts...>& { return c; }(t)} -> std::same_as<T&>;

    // simplified version, but allows conversion
    //[] <typename... Ts>(C<Ts...>&) {}(t);
};

Demo 虽然不被 clang 接受。

【讨论】:

  • 即使被接受,该版本也允许在将T 传递给立即调用的 lambda 表达式时隐式转换为C&lt;Ts...&gt;edit 还是将参数标记为左值引用会阻止这种情况?也许你是对的。
  • @PatrickRoberts:std::same_as&lt;T&amp;, C&lt;Ts&gt;&amp;&gt; 有一个额外的约束应该可以解决这个问题
  • 哦,我忘了std::same_as 也填充了C&lt;Ts...&gt;&amp;,这是有道理的。
猜你喜欢
  • 2018-10-21
  • 1970-01-01
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
  • 2021-02-16
  • 1970-01-01
  • 2012-12-07
  • 1970-01-01
相关资源
最近更新 更多