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,对不起,如果这个问题有点让人困惑。我真的在问学习的目的,看看是否有一种方法,这甚至是可能的 在下面的类中,我必须为CreateObject()和GetObject()指定一个模板参数: 类对象管理器 { 公众: 模板 void CreateObject(int-id) { //在地图中存储指向新创建对象的指针 } 模板 T*GetObject(int id) { //使用id查找对象并向其返回T* } }; CreateObject()使用模板参数创建正确类型的对象,然后在映射中存储指向该对象

对不起,如果这个问题有点让人困惑。我真的在问学习的目的,看看是否有一种方法,这甚至是可能的

在下面的类中,我必须为CreateObject()和GetObject()指定一个模板参数:

类对象管理器
{
公众:
模板
void CreateObject(int-id)
{
//在地图中存储指向新创建对象的指针
}
模板
T*GetObject(int id)
{
//使用id查找对象并向其返回T*
}
};
CreateObject()使用模板参数创建正确类型的对象,然后在映射中存储指向该对象的指针。GetObject()使用模板参数返回所需类型的指针。对于某些对象,我希望GetObject()返回指向实际对象类型的指针。对于其他对象,我希望GetObject()返回指向父类型的指针

现在,无论何时调用GetObject(),我都需要指定类型:

SomeType* pST = m_objectManager.GetObject<SomeType>(id);
AnotherType* pAT = m_objectManager.GetObject<AnotherType>(id);
SomeType*pST=m_objectManager.GetObject(id);
另一个类型*pAT=m_objectManager.GetObject(id);
我的目标是在我的CreateObject()函数中指定实际对象类型和所需的返回类型作为模板参数:

class ObjectManager
{
public:
    template <class T, class DesiredReturnType>
    void CreateObject(int id)
    {
        //Store pointer to newly created object of type T in a map
        //The DesiredReturnType would be used by GetObject() to return the correct type of pointer
    }

    //This isn't possible but would be ideal.
    DesiredReturnType* GetObject(int id)
    {
        //Return a DesiredReturnType* to the object
    }
};

m_objectManager.CreateObject<SomeType, ParentOfSomeType>(id);

//Now I don't need to specify a template argument when calling GetObject().
//CreateObject() will create a new SomeType.
//GetObject() will return a ParentOfSomeType* which is really pointing to a SomeType object
ParentOfSomeType* pPST = m_objectManager.GetObject(id);
类对象管理器
{
公众:
模板
void CreateObject(int-id)
{
//在映射中存储指向新创建的T类型对象的指针
//GetObject()将使用DesiredReturnType返回正确类型的指针
}
//这是不可能的,但将是理想的。
DesiredReturnType*GetObject(int id)
{
//将DesiredReturnType*返回给对象
}
};
m_objectManager.CreateObject(id);
//现在,在调用GetObject()时,我不需要指定模板参数。
//CreateObject()将创建一个新的SomeType。
//GetObject()将返回SomeType*的父对象,该父对象实际上指向SomeType对象
父类sometype*pPST=m_objectManager.GetObject(id);
因为每个对象都有不同的类型和期望的返回类型,所以我不能使用类模板参数。根据我创建的对象类型的不同,类型和所需的返回类型始终会发生变化

这样的事情可能吗?在这种情况下,是否有某种设计模式会有所帮助

编辑:

设计选择的原因如下。我将调用另一个函数,该函数具有不同的行为,这取决于is接收的是父函数*还是子函数*

通过去掉template参数,我认为我可以做如下操作:

for(int id = 0; id < 10; id++)
MyFunction(m_objectManager.GetObject(id));
for(int-id=0;id<10;id++)
MyFunction(m_objectManager.GetObject(id));

这可能不会改变这样一个事实,即这是一个糟糕的决策选择,但我的提问主要是出于好奇。:)

关于类模板:

class ObjectManager
{
public:
   /// reference to some internal object manager 
   template <class T, class DesiredReturnType>
   class ObjectRef {
   public:
     ObjectRef(ObjectManager& manager) {}
     DesiredReturnType* GetObject()
     {
     }
   };
    template <class T, class DesiredReturnType>
    ObjectRef<T,DesiredReturnType> CreateObject(int id)
    {
    }
};

auto ref = m_objectManager.CreateObject<SomeType, ParentOfSomeType>(id);

//Now I don't need to specify a template argument when calling GetObject().
//CreateObject() will create a new SomeType.
//GetObject() will return a ParentOfSomeType* which is really pointing to a SomeType object
ParentOfSomeType* pPST = ref.GetObject(); // no need to specify id...
类对象管理器
{
公众:
///对某些内部对象管理器的引用
模板
类ObjectRef{
公众:
ObjectRef(ObjectManager和manager){}
DesiredReturnType*GetObject()
{
}
};
模板
ObjectRef CreateObject(int id)
{
}
};
auto ref=m_objectManager.CreateObject(id);
//现在,在调用GetObject()时,我不需要指定模板参数。
//CreateObject()将创建一个新的SomeType。
//GetObject()将返回SomeType*的父对象,该父对象实际上指向SomeType对象
某些类型的父类*pPST=ref.GetObject();//无需指定id。。。

> p> C++中的函数只能有一个返回类型,并且该类型必须在编译时知道。函数模板可以具有依赖于其模板参数的返回类型。因为C++是静态类型的,所以在编译时必须解决依赖关系。这意味着您无法在运行时从映射中查找所需的返回类型。但是,您可以从模板参数派生它

编辑:澄清:当您“使用”函数模板时,如
FunctionTemplate()
FunctionTemplate(使用ode铆钉模板参数的参数)
,函数模板将被实例化。这意味着将创建一个带有“name”
FunctionTemplate
的普通函数,即参数ARG1、ARG2等的模板的所谓“专门化”。该函数与普通函数类似,这意味着它也只能有一个在编译时必须知道的固定返回类型/编辑

换句话说:
GetObject
必须至少有一个用于派生返回类型的模板参数。根据您希望如何使用它,一件可能有效的事情是在
id
参数的类型中编码所需的返回类型

比如说

template <class T>
struct ObjectId {
    typedef T ReturnType;
    ObjectId(int id) : m_id(id) {}
    int m_id;
};

class ObjectManager {
    ...
    template <class T, class ID> // ID type will be deduced
    void CreateObject(ID id) {
        ...
    }

    template <class ID> // ID type will be deduced
    typename ID::ReturnType* GetObject(ID id) {
        ...
    }
};

...
ObjectManager obman;
auto const idFoo = ObjectId<Foo>(1);
auto const idBar = ObjectId<BarBase>(2);

obman.CreateObject<Foo>(idFoo);
obman.CreateObject<Bar>(idBar);
Foo* foo = obman.GetObject(idFoo);
BarBase* bar = obman.GetObject(idBar);
模板
结构对象{
typedef T ReturnType;
ObjectId(int-id):m_-id(id){}
国际货币基金组织;
};
类对象管理器{
...
模板//将导出ID类型
无效CreateObject(ID){
...
}
模板//将导出ID类型
typename ID::ReturnType*GetObject(ID){
...
}
};
...
对象管理器obman;
auto const idFoo=ObjectId(1);
auto const idBar=ObjectId(2);
创建对象(idFoo);
创建对象(idBar);
Foo*Foo=obman.GetObject(idFoo);
BarBase*bar=obman.GetObject(idBar);
尝试访客模式


完整代码:

#include <boost/shared_ptr.hpp>
#include <boost/ptr_container/ptr_map.hpp>
#include <iostream>
#include <ostream>
#include <map>

using namespace std;
using namespace boost;
typedef int ID;

struct SomeClass
{
    SomeClass()
    {
        cout << "SomeClass::SomeClass()" << endl;
    }
    ~SomeClass()
    {
        cout << "SomeClass::~SomeClass()" << endl;
    }
};

struct IVisitor
{
    virtual void visit(int)=0;
    virtual void visit(double)=0;
    virtual void visit(SomeClass&)=0;
    // ..
};

struct ConcreteVisitor: IVisitor
{
    virtual void visit(int)
    {
        cout << "visiting int" << endl;
    }
    virtual void visit(double)
    {
        cout << "visiting double" << endl;
    }
    virtual void visit(SomeClass&)
    {
        cout << "visiting SomeClass" << endl;
    }
    // ..
};

struct ITypeStorage
{
    virtual void apply_visitor(void *obj,IVisitor &visitor)=0;
};

template<typename ObjectType> struct TypeStorage: ITypeStorage
{
    virtual void apply_visitor(void *obj,IVisitor &visitor)
    {
        visitor.visit( *(static_cast<ObjectType *>(obj)) );
    }
};

class ObjectManager
{
    map<ID,boost::shared_ptr<void> > objects;
    ptr_map<ID,ITypeStorage> types;
public:
    template <class T>
    void create_object(ID id)
    {
        objects[id].reset(new T());//shared_ptr will use right deleter
        types.insert(id,new TypeStorage<T>());
    }
    void apply(ID id,IVisitor &visitor)
    {
        types.find(id)->second->apply_visitor(objects[id].get(),visitor);
    }
};

int main(int argc,char *argv[])
{
    ObjectManager manager;
    ConcreteVisitor visitor;

    manager.create_object<int>(1);
    manager.create_object<double>(2);
    manager.create_object<SomeClass>(3);

    manager.apply(1,visitor);
    manager.apply(2,visitor);
    manager.apply(3,visitor);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间boost;
typedef int-ID;
结构类
{
SomeClass()
{

cout“对于某些对象,我希望GetObject()返回指向实际对象类型的指针。对于其他对象,我希望GetObject()返回指向父类型的指针。”似乎是一个糟糕的设计。ObjectManager如何在内部存储对象?它是将所有对象存储在一个映射中,还是存储在不同的映射中?它可以从ID推断对象类型吗?我不确定你的意思。
object
是这里的实际对象还是更像一个
struct ConcreteVisitor: IVisitor
{
    virtual void visit(int)
    {
        cout << "visiting int" << endl;
    }
    virtual void visit(double)
    {
        cout << "visiting double" << endl;
    }
    virtual void visit(SomeClass&)
    {
        cout << "visiting SomeClass" << endl;
    }
    // ..
};
int main(int argc,char *argv[])
{
    ObjectManager manager;
    ConcreteVisitor visitor;

    manager.create_object<int>(1);
    manager.create_object<double>(2);
    manager.create_object<SomeClass>(3);

    manager.apply(1,visitor);
    manager.apply(2,visitor);
    manager.apply(3,visitor);
    return 0;
}
SomeClass::SomeClass()
visiting int
visiting double
visiting SomeClass
SomeClass::~SomeClass()
#include <boost/shared_ptr.hpp>
#include <boost/ptr_container/ptr_map.hpp>
#include <iostream>
#include <ostream>
#include <map>

using namespace std;
using namespace boost;
typedef int ID;

struct SomeClass
{
    SomeClass()
    {
        cout << "SomeClass::SomeClass()" << endl;
    }
    ~SomeClass()
    {
        cout << "SomeClass::~SomeClass()" << endl;
    }
};

struct IVisitor
{
    virtual void visit(int)=0;
    virtual void visit(double)=0;
    virtual void visit(SomeClass&)=0;
    // ..
};

struct ConcreteVisitor: IVisitor
{
    virtual void visit(int)
    {
        cout << "visiting int" << endl;
    }
    virtual void visit(double)
    {
        cout << "visiting double" << endl;
    }
    virtual void visit(SomeClass&)
    {
        cout << "visiting SomeClass" << endl;
    }
    // ..
};

struct ITypeStorage
{
    virtual void apply_visitor(void *obj,IVisitor &visitor)=0;
};

template<typename ObjectType> struct TypeStorage: ITypeStorage
{
    virtual void apply_visitor(void *obj,IVisitor &visitor)
    {
        visitor.visit( *(static_cast<ObjectType *>(obj)) );
    }
};

class ObjectManager
{
    map<ID,boost::shared_ptr<void> > objects;
    ptr_map<ID,ITypeStorage> types;
public:
    template <class T>
    void create_object(ID id)
    {
        objects[id].reset(new T());//shared_ptr will use right deleter
        types.insert(id,new TypeStorage<T>());
    }
    void apply(ID id,IVisitor &visitor)
    {
        types.find(id)->second->apply_visitor(objects[id].get(),visitor);
    }
};

int main(int argc,char *argv[])
{
    ObjectManager manager;
    ConcreteVisitor visitor;

    manager.create_object<int>(1);
    manager.create_object<double>(2);
    manager.create_object<SomeClass>(3);

    manager.apply(1,visitor);
    manager.apply(2,visitor);
    manager.apply(3,visitor);
    return 0;
}