Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 异构指针容器_C++_Templates - Fatal编程技术网

C++ 异构指针容器

C++ 异构指针容器,c++,templates,C++,Templates,我目前正在使用一个枚举映射到一个Base*数组中。枚举为每个派生类型提供一个索引 enum DerivedType { DERIVED_TYPE_1 = 0, DERIVED_TYPE_2, ... NUM_DERIVED_TYPES }; class Base { }; class Derived1 : public Base { static const DerivedType type; }; const DerivedType Deriv

我目前正在使用一个枚举映射到一个Base*数组中。枚举为每个派生类型提供一个索引

enum DerivedType {
    DERIVED_TYPE_1 = 0,
    DERIVED_TYPE_2,
    ...
    NUM_DERIVED_TYPES
};


class Base {

};


class Derived1 : public Base {
    static const DerivedType type;
};
const DerivedType Derived1::type = DERIVED_TYPE_1;


class Derived2 : public Base {
    static const DerivedType type;
};
const DerivedType Derived2::type = DERIVED_TYPE_2;


class Container {
    Base* obs[NUM_DERIVED_TYPES];

    template<class T>
    void addOb(T* ob) {
        obs[T::type] = ob;
    }

    template<class T>
    T* getOb() {
        return (T*) obs[T::type];
    }

    Base* getOb(DerivedType type) {
        return obs[type];
    }
};
枚举派生类型{
派生类型\u 1=0,
派生类型2,
...
NUM_派生类型
};
阶级基础{
};
类Derived1:公共基{
静态常量派生类型;
};
const-DerivedType-Derived1::type=DERIVED_-type_-1;
派生类2:公共基{
静态常量派生类型;
};
const-DerivedType-Derived2::type=DERIVED_-type_-2;
类容器{
基本*obs[NUM_派生的_类型];
模板
void addOb(T*ob){
obs[T::type]=ob;
}
模板
T*getOb(){
返回(T*)obs[T::type];
}
基本*getOb(DerivedType类型){
返回obs[类型];
}
};
由于每个派生类型的索引在编译时是已知的,有没有办法让非模板
getOb(DerivedType类型)
返回正确的DerivedN指针,可以通过在int->typename映射中查找typename?还是有更好的方法来实现这种模式?另外,让每个派生类型将自己添加到为其分配索引值的任何数据结构中也很好

基本上,我需要一个静态异构指针容器,它可以通过类型或索引访问,同时返回正确的派生*。我猜Boost有一些东西可以用,但我还没有找到

感谢您的帮助。

(1)
有没有办法让“非模板”getOb(DerivedType类型)返回正确的DerivedN指针

不幸的是,这是不可能的。对于非模板函数,返回类型只能是单个类型,并且在您的情况下必须是
Base*
type。
Base*getOb(DerivedType)的当前实现是正确的

(2)
有没有更好的方法来实现这种模式?

至少可以通过使用模板化的中间类(没有任何开销)简化工作,这将为您初始化
DerivedType
变量。例如,声明如下内容:

template<DerivedType TYPE>
struct Link : Base {
  static const DerivedType type;
};
template<DerivedType TYPE>
const DerivedType Link<TYPE>::type = TYPE;
模板
结构链接:基本{
静态常量派生类型;
};
模板
const-DerivedType链接::type=type;
现在,应该为派生类继承
链接
,例如:

class Derived1 : public Link<DERIVED_TYPE_1> {
// no need to declare/define an explicit variable for DerivedType now.
};
class-Derived1:公共链接{
//现在无需为DerivedType声明/定义显式变量。
};

好吧,我觉得你现在拥有的东西很可靠。我看到的唯一问题是,在运行时只有
Base*
可用,因为单个函数只能返回1种类型。要允许多类型返回而不必指定额外的参数,可以仿造如下函数:

// if employed as a free function
class getOb{
  DerivedType _type;
public:
  getOb(DerivedType type)
    : _type(type) {}

  template<class T>
  operator T*() const{
    Base* ptr;
    // fetch correct pointer from wherever
    // using _type, if non-existant use 0
    return (T*) ptr;
  }
};
参数在构造函数中传递,而实际函数体在转换运算符中。当然,这看起来只是一个独立函数,所以如果您想将其作为一个成员函数来实现,下面是它的外观

class GetObClass{
  mutable DerivedType _type;
public:
  GetObClass& operator()(DerivedType type) const{
    _type = type;
    return *this;
  }

  // template conversion operator as before
};
用法如

Derived1* pd = getOb(DERIVED_TYPE_1);
assert(pd != 0);
class Container{
public:
  const GetObClass getOb;
};

Container c;
Derived1* pd = c.getOb(DERIVED_TYPE_1);
assert(pd != 0);

虽然我不是100%确信我正确理解了这个问题, 也许你提到的(或类似的)可以实现 使用
boost::fusion
boost::mpl

例如:

#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/at_key.hpp>
#include <boost/mpl/vector.hpp>
namespace bf = boost::fusion;
namespace bm = boost::mpl;

// This order has to match with the enumerators in DerivedType
typedef bm::vector< Derived1, Derived2 > DerivedTypes;

typedef bf::map< bf::pair< Derived1, Derived1* >
               , bf::pair< Derived2, Derived2* > > Container;

int main() {
    Container c( bf::make_pair< Derived1, Derived1* >(0)
               , bf::make_pair< Derived2, Derived2* >(0) );
    Derived1 d1;
    Derived2 d2;
    bf::at_key< Derived1 >( c ) = &d1; // access with type
    bf::at_key< Derived2 >( c ) = &d2;
    // access with enum
    bf::at_key< bm::at_c< DerivedTypes, DERIVED_TYPE_1 >::type >( c ) = &d1;
    bf::at_key< bm::at_c< DerivedTypes, DERIVED_TYPE_2 >::type >( c ) = &d2;
}
#包括
#包括
#包括
名称空间bf=boost::fusion;
名称空间bm=boost::mpl;
//此顺序必须与DerivedType中的枚举数匹配
typedef bm::vectorDerivedTypes;
typedef bf::map
,bf::对>容器;
int main(){
容器c(bf::make_pair(0)
,bf::make_pair(0));
衍生1 d1;
衍生2 d2;
bf::at_key(c)=&d1;//使用类型进行访问
bf::at_键(c)=&d2;
//使用枚举访问
bf::at_key::TYPE>(c)=&d1;
bf::at_key::TYPE>(c)=&d2;
}

非常好,正是我想要的,谢谢。我所做的一个改进是让映射从向量自动填充:
typedef bm::fold::type容器