gnz*_*lbg 61 c++ higher-kinded-types c++-concepts
我正在尝试使用Concepts Lite来指定一个概念来约束具有成员函数模板的更高级的kinded类型.但是,我无法在技术规范或教程中找到一个处理概念中模板化语句的子句.
这是怎么做到的?
示例:假设我HKT的成员函数模板具有更高的kinded类型F:
template<class T>
struct HKT {
template<class U> // this looks like e.g. rebind in std::allocators
auto F(U) -> HKT<U>;
};
Run Code Online (Sandbox Code Playgroud)
现在我想指定一个约束这些更高级的类型的概念:
template <template <class> class HKT, class T>
concept HKTWithTemplateMemberFunctionF {
return requires(HKT<T> h) { // HKT<T> is a type, h is an object
// HKT<T> needs to have a member function template that
// returns HTK<U> where the type U is to be deduced and
// it can be any type (it is unconstrained)
template<class U> // is there a syntax for this?
h.F(std::declval<U>()) -> HKT<U>;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我可以这样做:
template <template <class> class HKT, class T, class U>
concept HKTWithTemplateMemberFunctionF {
return requires(HKT<T> h) {
h.F(std::declval<U>()) -> HKT<U>;
}
}
Run Code Online (Sandbox Code Playgroud)
但这意味着我需要知道U约束网站.
我真的不关心给定的替换是否U失败,尽管我可以看到为什么这可能是一个问题:例如,应用约束以确保您的函数不会失败然后失败导致约束被满足但是在实例化时成员函数模板中的替换失败(如果成员函数模板受约束会有帮助吗?).
长话短说,现在你(我?)必须提供一个具体的U:
template <template <class> class HKT, class T, class U = T>
concept HKTWithTemplateMemberFunctionF {
return requires(HKT<T> h) { // HKT<T> is a type, h is an object
h.F(std::declval<U>()) -> HKT<U>;
}
}
Run Code Online (Sandbox Code Playgroud)
因为编译器无法证明U成员函数模板可能存在的所有类型,也就是说,以下内容是没有希望的:
template <template <class> class HKT, class T>
concept HKTWithTemplateMemberFunctionF {
return requires(HKT<T> h) {
template<class U> // for all those Us that haven't been written yet...
h.F(std::declval<U>()) -> HKT<U>;
}
}
Run Code Online (Sandbox Code Playgroud)
在一个假设的5分钟概念设计实现中,我们能够限制U 一点点:
template <template <class> class HKT, class T,
InputIterator U = InputIterator() /* imaginary syntax */ >
concept HKTWithTemplateMemberFunctionF {
return requires(HKT<T> h) {
h.F(std::declval<U>()) -> HKT<U>; // Is InputIterator enough to instantiate F?
}
}
Run Code Online (Sandbox Code Playgroud)
编译器只需要检查一个模型InputIterator是否足以实例化h.F,即使h.F没有约束也是如此!另外U只提供它模型的检查,InputIterator甚至不需要尝试检查h.F,U因为这InputIterator已经足够了.这可用于优化编译时性能和......
...可能会以令人惊讶的方式与SFINAE交互,因为AFAIK你可以拥有一个概念重载函数(例如for InputIterator),它接受除了那个之外的所有输入迭代器(SFINAE!为什么会有人这样做?!),因此可以通过概念检查,但在实例化时间吹...悲伤.
让我们从您的评论中考虑一下您想要的要求:
Run Code Online (Sandbox Code Playgroud)// HKT<T> needs to have a member function template that // returns HTK<U> where the type U is to be deduced and // it can be any type (it is unconstrained)
虽然概念要求我们将约束建立在具体类型的基础上,但我们可以明智地选择我们使用的具体类型。你所说的任何U类型是什么意思。真的任何类型都可以吗?考虑一下您所面临的最小可能的约束集,然后让我们构建一个满足它们的类型。这被称为的原型。UU
我首先想到的“任何类型”实际上是半规则类型。默认可构造、可复制和可分配的类型。所有正常的好东西:
namespace archetypes {
// private, only used for concept definitions, never in real code
struct Semiregular { };
}
Run Code Online (Sandbox Code Playgroud)
archetypes::Semiregular是一个具体类型,所以我们可以用它来构建一个概念:
template <template <class> class HKT, class T>
concept bool HKTWithTemplateMemberFunctionF =
requires(HKT<T> h, archetypes::Semiregular r) {
{h.F(r)} -> HKT<archetypes::Semiregular>
};
Run Code Online (Sandbox Code Playgroud)
archetypes::Semiregular是私有类型。它不应该为 所知HKT,因此如果h.F(r)格式良好并且返回可转换为 的类型HKT<archetypes::Semiregular>,那么它几乎肯定是一个成员函数模板。
那么问题是,这是一个好的原型吗?我们是否需要U半规则类型,或者不规则类型也可以工作?您需要的操作越少,原型中应该出现的操作就越少。也许您所需要的只是U可移动的:
namespace archetypes {
// private, only used for concept definitions, never in real code
struct Semiregular { };
struct Moveable {
Moveable() = delete;
Moveable(Moveable&& ) noexcept(false);
Moveable(Moveable const& ) = delete;
~Moveable() = default;
Moveable& operator=(Moveable const& ) = delete;
Moveable& operator=(Moveable&& ) noexcept(false);
};
}
template <template <class> class HKT, class T>
concept bool HKTWithTemplateMemberFunctionF =
requires(HKT<T> h, archetypes::Moveable m) {
{ h.F(m) } -> HKT<archetypes::Moveable>
};
Run Code Online (Sandbox Code Playgroud)
我们正在测试相同的想法 - 使用F()不为人所知的类型进行调用,并排除返回类型以反映这一点,因此要求它是一个函数模板。但现在我们为该类型提供的功能较少。如果F()适用于任何,它也会适用于archetypes::Moveable。
不断迭代这个想法,直到您真正将所需的功能削减到最低限度。也许你甚至不需要原型是可破坏的?编写原型很困难,但在这种情况下,正确编写原型很重要。