查询getInstance <t>()时的最小实例化类对象,基于继承

时间:2017-04-02 10:44:19

标签: c++ c++11 templates inheritance singleton

我的图书馆用户将通过getInstance<T>()要求提供任何课程的实例。

用户在某个程序中询问(调用{T1,T2,T3,...,Tn}的外观)的所有类getInstance<T>()中,如果有一对(i,j)Ti派生自{{ 1}},我只会创建更大的一个,例如Tj

这是一个例子 假设用户的代码代码要求我创建这些类: -

  • Physic
  • 刚性
  • 约束
  • 图形

    他们的继承如下: -

(以上四个类在图中标有黄色。)

enter image description here

我的代码将创建覆盖整棵树的最小数量的类实例 在这种情况下,最佳解决方案是 3 TiRigidConstraint
粗略地说,三个箭头传递树中的所有类。

enter image description here

在这种情况下,会有Graphic的2个实例,但我不在乎。 (感谢Christian Hackl)

更具体地说,Physic可以返回任何一个 基础类型可以是getInstance<Physic>()Rigid* - 两者都可以。

如果有很多最低解决方案,那么其中任何一个都可以。

这就是我的梦想: -

Constraint*

怎么做?
这是最接近的问题:Create "custom typeid" for many types AND cache their sizeof()

我觉得有可能:我必须使用以下方法缓存类型: -

  • lambda without capture / //..... some list to cache std::function .... ? template<class T> T* getInstance(){ //return new T() ? } class B{}; class C{}; class D : public B{}; int main(){ //..... allow to insert some code here ...... (a little less preferable) B* b=getInstance<B>(); //return B* (implicitly cast D*->B*) C* c=getInstance<C>(); //return C* D* d=getInstance<D>(); //return D* assert( static_cast<D*>(b) == d ); delete d; delete c; //no memory leak } - &gt;将其保存在列表中
  • 缓存函数调用std::function
  • 然后,我必须以某种方式识别所有叶子节点。
  • 必须实例化的类的数量=叶节点的数量。

然而,这远非一个具体的想法。

我想为我的图书馆+教育目的创建一个非常复杂的单身经理 我知道这不是一个好习惯,但我相信这个解决方案会启发我在C ++领域 以防它不是那么明显 - 这不是作业/面试。

1 个答案:

答案 0 :(得分:1)

你主要需要一个类型特征,给定一个类型和一个类型列表,从列表中返回一种顶级派生类型。

不是很优雅(我试着把它简化一下)但是下面的代码应该给你一个例子

#include <cassert>
#include <iostream>
#include <type_traits>

struct core {};
struct physic     : public core {};
struct rigid      : public physic {};
struct constraint : public physic {};
struct graphic    : public core {};

template <typename ... Ts>
struct contTypes
 { };

template <typename T0, typename T1>
struct isStrictBase
 { static constexpr bool value =
         (false == std::is_same<T0, T1>::value)
      && (true == std::is_base_of<T0, T1>::value); };

template <bool, typename...>
struct chooseT;

template <typename, typename, typename>
struct getTopTypeH;

template <typename C0, typename T, typename T0, typename C1>
struct chooseT<true, C0, T, T0, C1>
 { using type = typename getTopTypeH<C0, T0, C0>::type; };

template <typename C0, typename T, typename T0, typename C1>
struct chooseT<false, C0, T, T0, C1>
 { using type = typename getTopTypeH<C0, T, C1>::type; };

template <typename, typename, typename>
struct getTopTypeH;

template <template <typename ...> class Ct, typename ... Ts0, typename T>
struct getTopTypeH<Ct<Ts0...>, T, Ct<>>
 { using type = T; };

template <template <typename ...> class Ct, typename ... Ts0,
          typename T, typename T0, typename ... Ts>
struct getTopTypeH<Ct<Ts0...>, T, Ct<T0, Ts...>>
 {
   using type = typename chooseT<isStrictBase<T, T0>::value,
                                 Ct<Ts0...>, T, T0, Ct<Ts...>>::type;
 };

template <typename T, typename CT>
struct getTopType
 { using type = typename getTopTypeH<CT, T, CT>::type; };


template <typename T>
struct staticWrapper
 {
   static T * getPnt ()
    {
      static T st{};

      return & st;
    }
 };

using cT = contTypes<core, physic, rigid, constraint, graphic>;

template <typename T>
T * getInstance ()
 { return staticWrapper<typename getTopType<T, cT>::type>::getPnt(); }

int main ()
 {
   auto p0 = getInstance<core>();
   auto p1 = getInstance<physic>();
   auto p2 = getInstance<rigid>();
   auto p3 = getInstance<constraint>();
   auto p4 = getInstance<graphic>();

   assert( p0 == p1 );
   assert( p0 == p2 );

   std::cout << "assert passed" << std::endl;
 }