c++ - 如何将 Variadic CRTP 基类设置为派生类的朋友
问题描述
问题的主要部分是使用基于策略的设计和可变参数模板的CRTP。从策略无法访问主/派生类的受保护或私有成员。由于使用可变参数模板,我不能将策略声明为朋友。
问题是,如何将所有策略类设置为派生类的朋友。
鉴于此 CRTP 解决方案,什么是支持多继承级别并解决了没有虚拟继承的菱形问题。
// Derived - We would like to obtain access to this type of instance
// BaseDerived - Helper type to avoid the diamond problem without virtual inheritance
template<typename Derived, template<typename> class BaseDerived>
class Crtp {
protected:
[[nodiscard]] constexpr Derived & underlying() noexcept
{
return static_cast<Derived &>(*this);
}
[[nodiscard]] constexpr Derived const & underlying() const noexcept
{
return static_cast<Derived const &>(*this);
}
};
// Helper struct to achive multiple inheritance
struct NoDerivedClassTag;
template<template<typename> class Derived, typename Substitute, template<typename> class Base>
using DerivedCrtpBase = Base<std::conditional_t<std::is_same_v<Substitute, NoDerivedClassTag>, Derived<NoDerivedClassTag>, Substitute>>;
template<template<typename> class Interface, typename Object>
using is_crtp_interface_of = std::enable_if_t<
std::is_same_v<Interface<NoDerivedClassTag>, Object> || std::is_base_of_v<Interface<typename Object::exact_type>, Object>>;
在带有可变参数模板的基于策略的设计中使用此 CRTP 解决方案
template<template<typename> class... Functionality>
class FinalDerived
: public Functionality<FinalDerived<Functionality...>>...
{
public:
constexpr int get() const
{
return protected_variable_;
}
// Remove to check the problem
//protected:
int protected_variable_ {-1};
};
目标是像这样使用策略中的受保护变量
template<typename Derived>
struct Increment
: Crtp<Derived, Increment>
{
void increment(int an_value)
{
this->underlying().protected_variable_ += an_value;
}
};
template<typename Derived>
struct Decrement
: Crtp<Derived, Decrement>
{
void decrement(int an_value)
{
this->underlying().protected_variable_ -= an_value;
}
};
使用示例
constexpr int number {7};
int main(void){
FinalDerived<Increment, Decrement> derived;
std::cout << "start: " << derived.get() << "\n";
derived.increment(number);
std::cout << "incremented: " << derived.get() << "\n";
derived.decrement(number);
std::cout << "decremented: " << derived.get() << "\n";
}
解决方案
我能想到的一个解决方案是使用特征类,由您在 CRTP 基础和策略之前创建和定义的类继承,因此它们将是完整的类。Trait 类可能包含指向您需要访问的成员的指针或引用,具有这些特征的类共享的类型声明等,看看它在标准组件中是如何完成的
推荐阅读
- ms-access - MS Access 查询:用单个字符替换字符串中的所有字符
- r - 在 R 中使用循环导入和合并 .csv 文件
- transparency - Gimp 2.8.22:更改颜色并保持透明度
- css - 如何实现 Angular 6+ Bootstrap 标签集右对齐标签?
- recursion - 以递归方式使用机器学习预测时间范围
- kotlin - Kotlin 类应该有一个无参数构造函数
- daml - 如何在 DAML 中提取元组的组件?
- php - 从数组或对象在 php 中生成 CSV
- c++ - 如何在 matlab 上修复(使用 mexOpenCV 时出错)?
- amazon-web-services - 如何启动具有从列表中选择的多个 SG 的实例