概念可以与 CRTP 习语一起使用吗?
Can concepts be used with CRTP idiom?
给出以下奇怪的重复模板模式 (CRTP) 代码示例:
template<typename X>
struct Base {
X f() const { return X{}; }
};
template<template<typename> typename T>
struct Derived : T<Derived<T>>
{};
const Derived<Base> d0{};
const Derived<Base> d1 = d0.f();
我开始怀疑是否可以使用概念来限制可能的基集 类。我的想法,基于假设使用requires B<T, Derived<T>>
,其中B
定义如下:
#include <concepts>
// ...
template<template<typename> typename T, typename X>
concept B = requires (T<X> t)
{
{ t.f() } -> std::convertible_to<X>;
};
显然,我不能使用这种形式:
template<template<typename> typename T> requires B<T, Derived<T>>
struct Derived : T<Derived<T>>
{};
因为 require-clause 中的 Derived
尚未定义。这个:
template<template<typename> typename T>
struct Derived requires B<T, Derived<T>> : T<Derived<T>>
{};
还有这个:
template<template<typename> typename T>
struct Derived : T<Derived<T>> requires B<T, Derived<T>>
{};
也不解决问题
有没有办法克服这些困难并将概念与CRTP结合起来?
(我在 GCC 10.0.1 上进行了测试。)
我阅读了一项建议对 class 定义进行约束的提案。但它没有合并到标准中。因此,如果您想限制 class 定义,我知道的唯一解决方法是在完全定义 class 的上下文中使用静态断言,因此在成员函数体内:
template <class Base>
struct A: Base
{
A() {
static_assert(a_concept <A>);
}
};
给出以下奇怪的重复模板模式 (CRTP) 代码示例:
template<typename X>
struct Base {
X f() const { return X{}; }
};
template<template<typename> typename T>
struct Derived : T<Derived<T>>
{};
const Derived<Base> d0{};
const Derived<Base> d1 = d0.f();
我开始怀疑是否可以使用概念来限制可能的基集 类。我的想法,基于requires B<T, Derived<T>>
,其中B
定义如下:
#include <concepts>
// ...
template<template<typename> typename T, typename X>
concept B = requires (T<X> t)
{
{ t.f() } -> std::convertible_to<X>;
};
显然,我不能使用这种形式:
template<template<typename> typename T> requires B<T, Derived<T>>
struct Derived : T<Derived<T>>
{};
因为 require-clause 中的 Derived
尚未定义。这个:
template<template<typename> typename T>
struct Derived requires B<T, Derived<T>> : T<Derived<T>>
{};
还有这个:
template<template<typename> typename T>
struct Derived : T<Derived<T>> requires B<T, Derived<T>>
{};
也不解决问题
有没有办法克服这些困难并将概念与CRTP结合起来?
(我在 GCC 10.0.1 上进行了测试。)
我阅读了一项建议对 class 定义进行约束的提案。但它没有合并到标准中。因此,如果您想限制 class 定义,我知道的唯一解决方法是在完全定义 class 的上下文中使用静态断言,因此在成员函数体内:
template <class Base>
struct A: Base
{
A() {
static_assert(a_concept <A>);
}
};