简体   繁体   English

如何给结构一个“虚拟” typedef?

[英]How to give a struct a “virtual” typedef?

I have a struct BaseStorage that stores various run-time data, and a struct BaseStatic that holds a BaseStorage (or derived) typedef and "static" data that doesn't get changed and is read from multiple instances of a struct Holder . 我有一个结构BaseStorage存储各种运行时数据和结构BaseStatic持有一个BaseStorage不得到改变,并从一个结构的多个实例读取(或派生)的typedef和“静态”数据Holder Holder has a pointer to one of each, a const BaseStatic* to access that read-only, shared data and a BaseStorage* as its personal info store. Holder有一个指针指向每一个,一个const BaseStatic*访问只读,共享数据和BaseStorage*作为其个人信息存储。 The "static" data in BaseStatic is still populated at run-time (read from a file); BaseStatic的“静态”数据仍在运行时填充(从文件中读取); it is not constant! 它不是恒定的!

The idea here is that BaseStatic has a certain set of read-only data and functions that will be shared 1:N among many Holder instances. 这里的想法是BaseStatic具有一组特定的只读数据和函数,这些数据和函数将在许多Holder实例之间以1:N共享。 Each Holder will also have run-time info specific to its instance that needs to match the BaseStatic derived type. 每个Holder还将具有特定于其实例的运行时信息,该信息需要匹配BaseStatic派生类型。 So that's what BaseStorage derived stuff does, it holds the specific run-time info that a BaseStatic type will need. 所以,这就是BaseStorage派生的东西呢,它拥有特定的运行时间信息,一个BaseStatic类型需要。 Holder itself also stores data and has functions that are the same among all Holder s; Holder本身还存储数据,并且具有与所有Holder相同的功能; it isn't an inert container. 它不是惰性容器。

So I need a derived BaseStorage paired with each derived BaseStatic . 所以我需要一个派生BaseStorage与每个派生配对BaseStatic There will be many of these derived pairs. 这些派生对将有很多。

struct BaseStorage
{
 int something[2];
};

struct BaseStatic
{
 typedef BaseStorage Storage;

 //members and stuff
};


struct DerivedStorage : public BaseStorage
{
 std::string somethingelse;
};

struct DerivedStatic : public BaseStatic
{
 typedef DerivedStorage Storage;

 //other things
};


struct Holder
{
 const BaseStatic* base;
 BaseStorage* storage;
};

I have a builder function that does some stuff, among them populating storage. 我有一个生成器功能,可以完成一些工作,其中包括填充存储。 The only way I can think of doing it is with templates, like so: 我能想到的唯一方法是使用模板,例如:

template<typename T> Holder& builder(const T* base) //receives a BaseStatic
{
 Holder& holder = ...;

 //add to a list, etc

 holder.base = base;
 holder.storage = new T::Base();
}

However, that is going to result in a lot of templated functions getting made by the compiler for a very trivial thing (accessing a single type!). 但是,这将导致编译器为非常琐碎的事情(访问单个类型!)创建许多模板化函数。 Further I can never have params for my T::Base constructor (unless all structs have the same ones!). 此外,我永远无法为T :: Base构造函数提供参数(除非所有结构都具有相同的参数!)。 I'm sure this is terrible in other ways too. 我相信这在其他方面也很糟糕。

Is there any way to store a type that can be accessed virtually from BaseStatic without using templates? 有什么方法可以存储可以从BaseStatic虚拟访问而无需使用模板的类型? There's gotta be a better way. 有更好的方法。

There are various constraints that have led me to this setup, so I apologize if it's ugly. 有很多限制因素导致我无法进行此设置,因此,如果该设置很丑陋,我深表歉意。

Templating isn't as bad as you seem to think it is. 模板并不像您认为的那样糟糕。 Any polymorphic solution would likely require some sort of RTTI use, which would require comparisons and indirect branching -- potentially more or less expensive than a bunch of templated functions and depending on your requirements this could be bad, good or more likely, meaningless. 任何多态解决方案都可能需要某种RTTI用法,这将需要比较和间接分支-可能比一堆模板函数的价格昂贵或更低,并且取决于您的要求,这可能是不好的,很好的或更有可能的,毫无意义。 Remember, that the only one template will be instantiated per unique set of template parameters, so only one per base T in your case. 请记住,每个唯一的模板参数集将只实例化一个模板,因此在您的情况下,每个基数T都只实例化一个模板。

One solution to your constructor issue is to use C++11 Variadic Template args: 解决构造函数问题的一种方法是使用C ++ 11 Variadic Template args:

template<typename T, typename ...Args> 
Holder builder(const T* base, Args ...args) //receives a BaseStatic
{
  Holder holder;

  //add to a list, etc

  holder.base = base;
  holder.storage = new typename T::Storage(args...);
  return holder;
}

Note that for this to work, the derived storage types have to use private inheritance with BaseStorage , otherwise the Storage typedef becomes ambiguous. 请注意,要使此方法起作用,派生的存储类型必须对BaseStorage使用私有继承,否则Storage typedef会变得模棱两可。

Now this could blow up into a lot of functions depending on the scope of your project, but remember -- "don't optimize yet." 现在,根据项目的范围,这可能会分解为许多功能,但是请记住-“暂时不要优化”。

I used Raymond Chen's comment and created this method in BaseStatic : 我使用了Raymond Chen的注释,并在BaseStatic创建了此方法:

Storage* CreateStorage() const {return new Storage();}

And override it in DerivedStatic with: 并在DerivedStatic使用以下命令覆盖它:

Storage* CreateStorage() const {return new Storage();}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM