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