说我有以下
class thing {
template<typename T> void method(T value) {}
}
我想要做的是将value
传递给std::vector
的任何值存储到void*
或其他什么类型而不将其转换为模板类(因为这不能解决我的问题)无论如何都有问题)
我希望能够在不使用提升的情况下做到这一点(尽管我喜欢提升,但我不会一直使用它)
我最初使用的是union
,但是我会失去对象的类型,最终会导致不安全。
我的下一个想法是使用struct
/ union type_wrapper {
int a;
char f;
/* etc, etc, etc */
}
,如下所示:
template<typename T>
class type_wrapper {
T getType() { return /* get value of type/pointer/object here */ }
/*Stored in some manner */
}
但是我会遇到跟踪类型的问题,所以我确保它在使用时保持不变。
接下来我尝试的是一个类,它会在函数调用中返回类型:
std::list<AClass>
问题与单独使用类型是一回事,因为当类型为std::list<BClass>
或std::list<int>
等时,它无法存储在名为int
的列表中
我所看到的所有其他示例都做了我正在做的事情,但期望您以某种方式跟踪对象的类型,或使用提升。
我可以尝试这样做,以便我可以传递类型std::list
的参数并存储到{{1}}等,同时使用相同的模板函数传递类型'cheese'的参数(虚构的课程,致力于用奶酪填充您的程序)并将其存储在相同的列表等
答案 0 :(得分:2)
我不知道这是否会解决您的问题,但您可以为容器使用某种多态类型,并将该对象封装在通用派生类中,因此调用对象的成员函数来自派生班&#39;成员函数可以有完整的类型信息(它们将是专门的模板),但你的&#34;事物&#34;不会是通用的,客户代码不会关心(或甚至知道)这种关注:
class Aux {
public:
virtual void DoSomething() =0 ;
};
template<typename T>
class AuxTemp : public Aux {
T *real_obj;
public:
AuxTemp(const T &obj) : real_obj(new T(obj)) {} // create
AuxTemp(const AuxTemp &other) : real_obj(new T(*other.real_obj)) { } // copy
AuxTemp(AuxTemp &&other) : real_obj(other.real_obj) { other.real_obj=nullptr; } // move
~AuxTemp() { delete real_obj; } // destroy
void DoSomething() override {
real_obj->DoSomething(); // here we call the method with full type information for real_obj
}
};
class Thing {
std::vector<Aux*> v;
public:
template<typename T> void Add(const T &value) {
v.push_back(new AuxTemp<T>(value));
}
void DoSomethingForAll() {
for(auto &x:v) x->DoSomething();
}
};
哟可以用以下方式测试:
class A {
public:
void DoSomething() { std::cout << "A"<< std::endl; }
};
class B {
public:
void DoSomething() { std::cout << "B"<< std::endl; }
};
int main(int argc, char *argv[]) {
Thing t;
t.Add(A{});
t.Add(B{});
t.DoSomethingForAll();
return 0;
}
对于推送到向量的每个新类型,添加成员函数创建一个新的派生和专用包装类,因此虚拟表可以处理对DoSomething的调用,以便使用正确且完全意识到的实现类型版本。
我认为我提议的是一个奇怪的实现&#34; type-erasure&#34; (你应该谷歌这个术语来找到更详细的解决方案)。