我正在尝试使用指向非模板基类的指针来实现Heterogenous容器。派生类是模板。
注意:派生类类型在编译时是已知的。 注意:容器大小已修复。
第一次尝试:正在使用辅助数组来保存正确类型的整数表示。它的大小等于容器大小。然而,我最终得到了很多if语句。
我的问题与此thread略有相似,但我不知道如何使用std :: type_index。
我试图避免使用 Boost :: variant 和运行时多态来解决这个问题。
我的问题:是否有更好的方法来处理从基类到派生类的转换?
在我的实际问题中Edit1 。模板类有16种不同的类型。
示例:
template<typename Color, typename Smell, typename Shape, typename Origin>
class Fruit{};
实现:
class Plant
{ public: std::string sound = "I am jst a plant";};
template <typename T>
class Fruit : public Plant
{public: std::string sound = "I am jst a Fruit!";};
// list of types known at compile time.
struct Apple{ }; // types = 0
struct Orange{ }; // types = 1
struct Banana{ }; // types = 2
template <>
class Fruit<Apple> : public Plant
{public: std::string sound = "I am Apple";};
template <>
class Fruit<Orange> : public Plant
{public: std::string sound = "I am Orange";};
template <>
class Fruit<Banana> : public Plant
{public: std::string sound = "I am Banana";};
template <typename T>
void MakeSound(T fruit)
{
std::cout << fruit->sound << std::endl;
}
int main() {
Plant* Basket[5] = {nullptr};
int types[5] = {0};
Basket[0] = new Fruit<Apple>;
types[0] = 0;
Basket[1] = new Fruit<Orange>;
types[1] = 1;
Basket[2] = new Fruit<Orange>;
types[2] = 1;
Basket[3] = new Fruit<Apple>;
types[3] = 0;
Basket[4] = new Fruit<Apple>;
types[4] = 0;
for (int i = 0; i < 5; ++i)
{
if (types[i] == 0)
{
MakeSound(static_cast<Fruit<Apple> *>(Basket[i]));
}
else if (types[i] == 1)
{
MakeSound(static_cast<Fruit<Orange> *>(Basket[i]));
}
else
{
MakeSound(static_cast<Fruit<Banana> *>(Basket[i]));
}
}
}
答案 0 :(得分:1)
我建议使用虚函数来检测派生对象类型的id;我建议在模板类参数中注册的类型的id(作为sound
),以避免需要Fruit
的专业化。
并且请:你标记了C ++ 11;所以使用智能指针。
我的意思的一个例子
#include <string>
#include <vector>
#include <memory>
#include <iostream>
struct Plant
{ virtual std::size_t getTypeId () = 0; };
struct Apple
{
static constexpr size_t typeId { 0U };
static std::string const & getSnd ()
{ static std::string sound { "I am Apple" }; return sound; }
};
struct Orange
{
static constexpr size_t typeId { 1U };
static std::string const & getSnd ()
{ static std::string sound { "I am Orange" }; return sound; }
};
struct Banana
{
static constexpr size_t typeId { 2U };
static std::string const & getSnd ()
{ static std::string sound { "I am Banana" }; return sound; }
};
template <typename T>
struct Fruit : public Plant
{
virtual std::size_t getTypeId () override { return T::typeId; }
static std::string const & getSnd () { return T::getSnd(); }
};
template <typename T>
void MakeSound(T fruit)
{ std::cout << fruit->getSnd() << std::endl; }
int main()
{
std::vector<std::unique_ptr<Plant>> bask;
bask.emplace_back(new Fruit<Apple>);
bask.emplace_back(new Fruit<Orange>);
bask.emplace_back(new Fruit<Orange>);
bask.emplace_back(new Fruit<Apple>);
bask.emplace_back(new Fruit<Apple>);
bask.emplace_back(new Fruit<Banana>);
for ( auto const & up : bask)
{
switch ( up->getTypeId() )
{
case 0U:
MakeSound(static_cast<Fruit<Apple> *>(up.get()));
break;
case 1U:
MakeSound(static_cast<Fruit<Orange> *>(up.get()));
break;
case 2U:
MakeSound(static_cast<Fruit<Banana> *>(up.get()));
break;
default:
break;
}
}
}