简化使用 CRTP 模式的类的声明
Simplify declarations of classes that use the CRTP pattern
我使用"奇怪的重复模板模式"来继承静态成员变量和实例getter。听起来做作,但该项目将有许多子类,需要尽可能轻松地声明,而无需重复代码。
我想出了以下内容,效果很好:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
struct Base {
virtual void printStrings() = 0;
};
template <typename T>
struct static_strings: Base {
static std::vector<std::string> strings;
static void addString(const std::string& s) {
strings.push_back(s);
}
virtual void printStrings() {
for (auto s: T::strings) {
std::cout << s << std::endl;
}
}
};
template <typename T> std::vector<std::string> static_strings<T>::strings;
struct Sub1: static_strings<Sub1> {};
struct Sub2: static_strings<Sub2> {};
int main() {
Sub1::addString("test 1");
std::shared_ptr<Base> s1 = std::make_shared<Sub1>();
Sub2::addString("test 2");
std::shared_ptr<Base> s2 = std::make_shared<Sub2>();
std::cout << "s1: ";
s1->printStrings();
std::cout << "s2: ";
s2->printStrings();
return 0;
}
但是,我想进一步简化新子类的声明,因为现在我必须复制声明并在粘贴的行中两次更改类名 (struct Sub3: static_strings<Sub3> {};
(。我可以使用宏,但我想知道是否有非宏(模板?(方法来做到这一点?
您可以轻松更改Base
tp 获取一组模板模板参数来派生:
template <typename T, template<typename> typename... OtherBases>
struct Base : OtherBases<T>... {
[...]
};
struct Sub1: Base<Sub1, static_strings> {};
struct Sub2: Base<Sub2, static_strings> {};
这不是一个很大的胜利,但如果你有更多的crtp基类,这可能会有所帮助。不过,我无法想象一种在没有宏的情况下保存剩余重复的方法。
实时代码在这里。
对于shared_pointer的事情,您需要从其他非模板化基类派生。
struct AbstractBase {
virtual ~AbstractBase() = default;
virtual void printStrings() = 0;
};
template <typename T, template<typename> typename... OtherBases>
struct Base : AbstractBase, OtherBases<T>... {... };
然后,从该指针创建共享指针:
std::shared_ptr<AbstractBase> s1 = std::make_shared<Sub1>();
std::shared_ptr<AbstractBase> s2 = std::make_shared<Sub2>();
有关更新的示例,请参阅此处。
可以使用帮助程序类型:
struct helper : foo<helper>, bar<helper> {};
仅靠这一点是行不通的,因为从它继承的所有类型都将共享相同的基类。为了避免重复类型名称,您可以引入虚拟模板参数:
template <typename T>
struct foo {};
template <typename T>
struct bar{};
template <int x>
struct helper : foo<helper<x>>, bar<helper<x>> {};
using Sub1 = helper<1>;
using Sub2 = helper<2>;
int main () {
}
这就是你可以在没有宏的情况下做的事情。使用宏,您可以使用__COUNTER__
(gcc 有它,不确定其他宏(来获得不同的int
:
using SubA = helper<__COUNTER__>;
using SubB = helper<__COUNTER__>;
相关文章:
- .cpp和.h文件中的模板专用化声明
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 未在作用域中声明unordered_map
- C++避免重复声明的语法是什么
- 如何确保C++函数在定义之前声明(如override关键字)
- 错误:未在此范围内声明'reverse'
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 为什么在定义函数之前先声明它
- 简化使用 CRTP 模式的类的声明
- 在函数中声明的 ifStream 对象在发布模式下不起作用
- 在类声明中初始化 const 成员变量时在调试模式下出现异常
- 模板类的正向声明(访问者设计模式)
- 使用静态和避免单例模式声明全局变量
- 默认声明的属性?(状态设计模式)
- 单例设计模式 - 显式声明类外的构造函数
- 带有正向声明的C++Builder模式
- 可互换声明的变量具有相同的内存地址模式
- 如何在衍生类中重新声明模式
- 如何在使用装饰器和迭代器设计模式时声明友类
- c++如何知道在状态模式中向何处转发声明