(对于类型擦除,我的意思是隐藏有关类的一些或所有类型信息,有点像Boost.Any.)
我想要掌握类型擦除技术,同时也分享那些,我知道.我希望找到一些有人在他/她最黑暗的时刻想到的疯狂技巧.:)
我所知道的第一个也是最明显的,也是最常用的方法是虚函数.只需在基于接口的类层次结构中隐藏类的实现.许多Boost库都这样做,例如Boost.Any这样做是为了隐藏你的类型,而Boost.Shared_ptr这样做是为了隐藏(de)分配机制.
然后有一个函数指针指向模板化函数的选项,同时将实际对象保存在void*指针中,如Boost.Function确实隐藏了仿函数的实际类型.可以在问题的最后找到示例实现.
所以,对于我的实际问题:
你知道其他什么类型的擦除技术?如果可能的话,请提供示例代码,用例,您对它们的体验以及可能的进一步阅读链接.
编辑
(因为我不确定是否将此作为答案添加,或者只是编辑问题,我只会做更安全的问题.)
另一个很好的技术来隐藏没有虚函数或void*摆弄的东西的实际类型,是一个GMan在这里工作,与我的问题有关,这个问题究竟是如何运作的.
示例代码:
#include <iostream>
#include <string>
// NOTE: The class name indicates the underlying type erasure technique
// this behaves like the Boost.Any type w.r.t. implementation details
class Any_Virtual{
struct holder_base{
virtual ~holder_base(){}
virtual holder_base* clone() const = 0;
};
template<class T>
struct holder : holder_base{
holder()
: held_()
{} …Run Code Online (Sandbox Code Playgroud) 如果我有类似的东西
class Base {
static int staticVar;
}
class DerivedA : public Base {}
class DerivedB : public Base {}
Run Code Online (Sandbox Code Playgroud)
都将DerivedA与DerivedB共享相同的staticVar或者他们每人将获得自己?
如果我想让他们各自拥有自己的,你会建议我做什么?
C++模板上下文中的特化和实例化有什么区别.从我到目前为止所读到的内容,以下是我对专业化和实例化的理解.
template <typename T>
struct Struct
{
T x;
};
template<>
struct Struct <int> //specialization
{
//code
};
int main()
{
Struct <int> s; //specialized version comes into play
Struct <float> r; // Struct <float> is instantiated by the compiler as shown below
}
Run Code Online (Sandbox Code Playgroud)
Struct <float>由编译器实例化
template <typename T=float>
struct Struct
{
float x;
}
Run Code Online (Sandbox Code Playgroud)
我对模板实例化和专业化的理解是否正确?
我的代码介于 c++17 和 c++20 之间。具体来说,我们在 GCC-9 和 clang-9 上启用了 c++20,它只是部分实现。
在代码中,我们有非常大的多态类型层次结构,如下所示:
struct Identifier {
virtual bool operator==(const Identifier&other) const = 0;
};
struct UserIdentifier : public Identifier {
int userId =0;
bool operator==(const Identifier&other) const override {
const UserIdentifier *otherUser = dynamic_cast<const UserIdentifier*>(&other);
return otherUser && otherUser->userId == userId;
}
};
struct MachineIdentifier : public Identifier {
int machineId =0;
bool operator==(const Identifier&other) const override {
const MachineIdentifier *otherMachine = dynamic_cast<const MachineIdentifier*>(&other);
return otherMachine && otherMachine->machineId == machineId;
}
}; …Run Code Online (Sandbox Code Playgroud) 我像boost一样写了一个单例模板类:
template <typename _T>
class Singleton
{
public :
static _T* Instance()
{
static _T obj;
return &obj;
}
protected :
Singleton() {}
private :
struct ObjectCreator
{
ObjectCreator()
{
Singleton<_T>::instance();
}
};
static ObjectCreator object_creator;
};
template <typename _T>
typename Singleton<_T>::ObjectCreator Singleton<_T>::object_creator;
Run Code Online (Sandbox Code Playgroud)
我写了主要功能来测试它.
#include "Singleton.h"
class A : public Singleton <A>
{
public:
int a;
};
int main()
{
A::Instance()->a = 2;
}
Run Code Online (Sandbox Code Playgroud)
我知道我错误地输入了Instance in ObjectCreator的构造函数,奇怪的是我可以通过gcc-4.4.7正确编译它,然后我使用了clang-6.0,它打了我的错字.
我猜gcc可以做一些优化,因为我没有做任何事情ObjectCreator,所以它忽略了错误代码.
我有两个问题:
Ps:我知道boost会添加一个do_nothing函数ObjectCreate …
我经常发现自己想要编写表单的泛型类定义
public class Foo<ActualType extends Foo<ActualType>>
Run Code Online (Sandbox Code Playgroud)
例如,在这样的设置中:
public interface ChangeHandler<SourceType> {
public void onChange(SourceType source);
}
public class Foo<ActualType extends Foo<ActualType>> {
private final List<ChangeHandler<ActualType>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<ActualType> handler) {
handlers.add(handler);
}
@SuppressWarnings("unchecked")
protected void reportChange() {
for (ChangeHandler<ActualType> handler: handlers)
handler.onChange((ActualType) this);
}
}
public class Bar extends Foo<Bar> {
// things happen in here that call super.reportChange();
}
public static void main(String[] args) throws IOException {
Bar bar = new Bar();
bar.addChangeHandler(new ChangeHandler<Bar>() { …Run Code Online (Sandbox Code Playgroud) 考虑以下两个带有CRTP模式的代码:
template <typename Derived>
struct Base1 {
int baz(typename Derived::value_type) {
return 42;
}
};
struct Foo1 : Base1<Foo1> {
using value_type = int;
};
Run Code Online (Sandbox Code Playgroud)
template <typename Derived>
struct Base2 {
auto baz() {
return typename Derived::value_type {};
}
};
struct Foo2 : Base2<Foo2> {
using value_type = int;
};
Run Code Online (Sandbox Code Playgroud)
第一个编译失败,而第二个编译。我的直觉说,它们应该要么编译要么都不编译。现在,如果我们将autoin 替换Base2为显式类型:
template <typename Derived>
struct Base3 {
typename Derived::value_type baz() {
return typename Derived::value_type {};
}
};
struct Foo3 …Run Code Online (Sandbox Code Playgroud) 我首先要说的是,我明白只有非静态成员函数可以是虚拟的,但这就是我想要的:
出于内存管理的目的(这是一个有限ram的嵌入式系统),我希望静态分配重写函数.我接受这样的结果:使用静态函数,我将如何操作函数中的数据.
我目前的想法是,我可以通过使其成为实际上是静态的函数的包装来保持轻量级重载函数.
请不要告诉我,我需要重新思考我的设计.这就是我提出这个问题的原因.如果您想告诉我我最好使用c并使用回调,请指导我阅读一些阅读材料来解释使用面向对象方法的缺陷.有面向对象的设计模式是否符合我列举的要求?
我有一个表示一个树对象的类,它使用唯一的指针,构成树的一些节点,以及一个基于某些参数构造指向抽象节点类的指针的函数(它生成指向子类的指针,因为抽象节点是抽象的)
class AbstractNode
{
vector<unique_ptr<AbstractNode>> children;
public:
AbstractNode(arguments...);
// other stuff...
};
class Tree
{
unique_ptr<AbstractNode> baseNode;
// other stuff...
}
unique_ptr<AbstractNode> constructNode(AbstractNodeTypes type);
Run Code Online (Sandbox Code Playgroud)
abstractNode有各种子类,它们将包含在树中.子类为该类中的某些虚函数提供了不同的实现.
我希望能够通过创建一组具有相同类类型的新节点来复制我的树,这些类型是原始树中节点的不同副本.
如果我为AbstractNode深度复制子类的类编写自己的复制构造函数,我将不得不为所有子类编写复制构造函数AbstractNode,这看起来很烦人,因为唯一不能正确复制的是子指针.在这里使用复制构造函数也很烦人,因为我需要在调用它们之前将它们转换为正确的类型,我想.
有没有什么方法可以让编译器让我使用默认的复制构造函数来设置除孩子之外的所有东西.它可以将那些作为空指针或其他东西?然后我可以编写一个更简单的函数,只是递归地添加子项来复制树.
如果这是不可能的,那么任何人都知道这个问题是否有任何非丑陋的解决方案?
我们正在使用奇怪的重复模板模式来实现单例.但是,在最近的Clang版本中,我们得到了一个-Wundefined-var-template警告.建议的修复是添加"显式实例化声明".
我试图这样做,但后来我在编译单元中获得了"实例化后显式特化"的错误,其中单例模板类成员变量的定义是.
解决此警告突出显示的问题的适当构造是什么?
简化细节(已删除大部分逻辑,以制作MCVE):
SingletonBase.hh:
template < class T > class SingletonBase {
public:
static T * get_instance() {
if ( ! instance_ ) {
instance_ = T::create_singleton_instance();
}
return instance_;
}
private:
static T * instance_;
};
Run Code Online (Sandbox Code Playgroud)
Singleton.hh:
#include "SingletonBase.hh"
class Singleton : public SingletonBase< Singleton > {
friend class SingletonBase< Singleton >;
public:
int do_stuff(int v) { return v+2; }
private:
static Singleton * create_singleton_instance() {
return new Singleton;
}
};
Run Code Online (Sandbox Code Playgroud)
Singleton.cc:
#include "Singleton.hh"
template …Run Code Online (Sandbox Code Playgroud) c++ ×9
c++11 ×2
crtp ×2
templates ×2
auto ×1
c++20 ×1
clang ×1
clang++ ×1
comparison ×1
embedded ×1
gcc ×1
generics ×1
inheritance ×1
java ×1
polymorphism ×1
singleton ×1
static ×1
type-erasure ×1