CRTP 设计,其中基类实例化派生类指定的类型的成员

问题描述 投票:0回答:1

Evgcrtp-pass-types-from-driven-class-to-base-class 中所述,编译器无法推导出类

Impl::TType
声明中的类型
Base
:

template <typename Impl>
struct Base
{
  typename Impl::TType t;
};

struct MyImplementation : public Base<MyImplementation>
{
  using TType = int;
  TType t;

  MyImplementation(TType n) : t(n) {};
};

int main()
{
  MyImplementation mi(3);

  return 0;
}

但是,我想要一个 CRTP 设计,其中用户编写一个派生自

Base
的实现,唯一的要求是实现类指定类型
TType
,以便基类可以实例化该类型的成员。换句话说,类
Base
期望实现定义类型
TType
。例如,它可能必须对整数执行操作,但各种实现可以使用不同的 int 类型(例如 int、unsigned int、long、short ...)。因此,
TType
是特定于实现的,不应该涉及 Base 类。粗暴的方法是:

template <typename Impl, typename T>
struct Base
{
  T t;
};

struct MyImplementation : public Base<MyImplementation, T>
{
  using TType = T;  //uneccessary but left for consistency
  TType t;

  MyImplementation(TType n) : t(n) {};
};

但是这里类型

TType
确实 涉及
Base
并且留下了更多的错误空间。例如,如果用户想要模板
TType
,他/她需要编写
class MyImplementation : public Base< MyImplementation<T>, T >
,这是一个糟糕的 API(特别是如果
Base
需要定义多个类型;例如
public Base< MyImplementation<T, V, Q>, T, V, Q >
),使其成为容易犯错误,例如:

template <typename T, typename Q>
struct MyImplementation : public Base<MyImplementation<T, Q>, Q>
{
  using TType = T;
};

有人知道现代有效的方法吗?

c++ templates inheritance crtp type-deduction
1个回答
2
投票

你可以写一个特征来从一些实例化

T
中推断出
MyImplementation<T>

template <typename Impl> struct the_type;

template <typename T, template<typename> typename Impl> 
struct the_type<Impl<T>> { using type = T; };

template <typename T> struct X {};

template <typename Impl>
struct Base {
    using T = typename the_type<Impl>::type;
};

但是,这仅适用于具有单个类型参数的类模板。它可以变得更通用以允许任何数量,但是一旦用户模板混合类型和非类型模板参数,你就不走运了。此外,对于您的

Base
来说,
Impl
T
之间的关系实际上并不重要。
Impl
可以是不是模板实例化的类型。
Impl
是否是
SomeTemplate<T>
是一个实现细节。因此,我更喜欢你分别通过
Impl
T
的方法。

© www.soinside.com 2019 - 2024. All rights reserved.