gpt4 book ai didi

c++ - 我可以将派生类的模板参数转发到 CRTP 中的基类吗?

转载 作者:太空宇宙 更新时间:2023-11-04 11:30:14 24 4
gpt4 key购买 nike

假设我有一个派生类Derived。除了采用模板参数外,Derived 还是 Base 的派生类,后者又在 Derived 上进行模板化。

下面举例说明了一个可行的解决方案:

template <int i, typename T>
class Derived : public Base<Derived<i,T>>
{
};

template <typename DerivedType>
class Base
{
};

然而,当 Derived 的模板参数列表变大时,这就变得很痛苦,因为想要将派生类添加到库中的编码人员必须编写两次模板参数。有什么方法可以自动执行此操作吗?

这就是我所追求的(以下内容无法编译,因为 this 尚不存在,但它说明了我正在寻找的内容):

template <int i, typename T>
class Derived : public Base<decltype(*this)>
{
};

template <typename DerivedType>
class Base
{
};

如果没有办法用模板实现这一点,我愿意接受一个优雅的宏解决方案(也许矛盾?)。

最佳答案

使用特征类来包含元数据,而不是传递参数列表中的每个项目。

这是我在我正在编写的库中所做的,很快就会开源。

首先,有默认的 traits 类来涵盖常见情况。我想处理一系列常见情况,所以它也是一个模板,但除此之外它可能是一个常规类。参数化只是方便用户的,不是最终的具体实现参数化,而是包含其内容。

template< typename rep_type, unsigned mantissa_values, rep_type fractional_cycles >
struct positive_logarithm_default_traits {
typedef double conv_basis;
static constexpr bool range_check = true;
typedef rep_type rep;

protected:
static constexpr rep max_rep = std::numeric_limits< rep >::max();
static constexpr rep unity_rep = mantissa_values * fractional_cycles;

// Another specialization could overflow to INFINITY and underflow to 0.
[[noreturn]] static rep underflow() { throw range_error( false ); }
[[noreturn]] static rep overflow() { throw range_error( true ); }
};

然后我定义了一个元函数来将类的一个实例转换为另一个实例。它在 traits 类空间内工作,如果多个元处理转换串在一起,这可以通过消除中间结果的实例化来帮助编译时间。

// The traits of a logarithm which represents the inverse of another logarithm.
template< typename traits >
struct inverse_traits : traits {
static constexpr decltype( traits::unity_rep ) unity_rep
= traits::max_rep - traits::unity_rep;
};

虽然 traits 类通常只包含编译时数据,但我会通过继承它来允许运行时变化。在这种情况下,特征类可能还想访问派生类的状态。这本质上就是 CRTP。但是,一个给定的 traits 类可能希望为几个具有非 traits 参数化的最终派生类提供服务。因此,我通过 static_cast< logarithm_state_base< traits > >( * this ) 创建了一个附加类,其运行时状态可供特征类访问— 这在功能上等同于 CRTP,但避开了很多元编程的复杂性。

template< typename traits >
class logarithm_state_base : public traits {
protected:
typename traits::rep log_value;
};

最后,派生类向用户提供与默认特征类解释相同的方便接口(interface)。但在内部,它通过从 traits 类继承的成员引用所有元数据。

如果用户定义了自己的traits类,那么typename traits_type之前的模板参数(除了 mantissa_values)是残留的和未使用的。别名模板可以将它们全部设置为 void提供一个完全基于特征的用户界面。或者,如果我预计 traits 的使用会更流行,我可以用另一种方式来做,让 traits 成为“ native ”接口(interface),逐项参数成为方便的别名。

template<
typename rep, // Underlying representation type
unsigned mantissa_values, // # distinct values per power of 2
rep fractional_cycles = std::numeric_limits< rep >::max() / ( mantissa_values * 2 ) + 1,
typename traits_type = positive_logarithm_default_traits< rep, mantissa_values, fractional_cycles >
>
class static_positive_logarithm
: public logarithm_state_base< traits_type > {
static_assert ( std::is_unsigned< typename traits_type::rep >::value,
"Representation type must be unsigned." );


关于c++ - 我可以将派生类的模板参数转发到 CRTP 中的基类吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25049365/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com