概念可以与 CRTP 习语一起使用吗?

Can concepts be used with CRTP idiom?

本文关键字:一起 习语 CRTP      更新时间:2023-10-16

给出了以下奇怪的重复出现的模板模式(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>>
{};

因为尚未定义要求子句中的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上进行了测试。

我读过一个提议对类定义约束的提案。但它没有合并到标准中。因此,如果你想约束类定义,我知道的唯一解决方法是在完全定义类的上下文中使用静态断言,所以在成员函数体内:

template <class Base>
struct A: Base 
{
A() {
static_assert(a_concept <A>);
}
};