C++:如何在地图中使用不同的动态模板
C++: How to use different dynamic template in map
我的header代码:
template <typename T>
class A
{
}
template<> class A<short>;
template<> class A<float>;
在我的cpp中,我想用一个map来包含不同类型的a,就像下面的代码:
class B
{
map<int, A*> a; /* how to declare a */
public:
AddA(int key, int type)
{
if (type == 1)
{
a.insert({ key, new A<short>() });
}
else
{
a.insert({ key, new A<float>() });
}
}
template<typename T>
func(int key, T v)
{
a[key].func(v);
}
};
提问:如何实现?
编辑@0410,这是我的解决方案:
class ABase
{
virtual void func(void* t)=0;
}
template <typename T> A;
template <short> A : public ABase
{
void func(void* t) override
{
auto value = *static_cast<short*>(t);
// do processing
}
template <float> A : public ABase
{
void func(void* t) override
{
auto value = *static_cast<float*>(t);
// do processing
}
CPP:为所有模板使用了 ABase* 映射 class,并为所有模板接口使用了虚函数
main()
{
map<int, ABase*> objs;
objs.insert({0, new A<short>()});
objs.insert({1, new A<float>()});
auto value=0;
objs[0]->func(&value);
auto value1=0.f;
objs[1]->func(&value1);
}
你不能用模板来解决问题。模板声明只是候选类型的蓝图。
“A”是不是“A”本身的类型。
你可以通过继承来解决你的问题。
编辑:代码已根据@MSalters 的评论更新。谢谢
#include <iostream>
#include <map>
class A
{
public:
virtual void func(void* x) = 0;
};
class A_Short : public A
{
public:
void func(void* x)
{
short* value = static_cast<short*>(x);
std::cout << "short value: " << *value << std::endl;
}
};
class A_Float : public A
{
public:
void func(void* x)
{
float* value = static_cast<float*>(x);
std::cout << "float value: " << *value << std::endl;
}
};
template<typename T>
class A_Derived : public A
{
public:
void func(void* x)
{
T* value = static_cast<T*>(x);
std::cout << "[Derived] value: " << *value << std::endl;
}
};
class B
{
std::map<int, A*> a; /* how to declare a */
public:
void AddA(int key, int type)
{
if (type == 1)
{
a.insert({ key, new A_Short() });
}
else if(type == 2)
{
a.insert({key, new A_Derived<short>()});
}
else if(type == 3)
{
a.insert({key, new A_Derived<float>()});
}
else
{
a.insert({ key, new A_Float() });
}
}
// Assumes that user knows to use which T for any "key"
template<typename T>
void func(int key, T v)
{
a[key]->func(v);
}
};
int main()
{
B b;
b.AddA(1, 1);
b.AddA(2, 8);
b.AddA(3, 2);
b.AddA(4, 3);
short s = 1;
float f = 7.1;
short s2 = 2;
float f2 = 7.2;
b.func(1, &s);
b.func(2, &f);
b.func(3, &s2);
b.func(4, &f2);
}
如果你确实需要在一个地图中有多种类型,你可以使用std::variant
的地图。但是正如评论中已经提到的,这可能是一个设计问题。
但是如果你需要的话,你可以继续std::map< int, std::variant<>>
。稍后,如果你想访问存储的元素,你必须调用 std::visit
来选择存储在 std::variant
.
中的元素
参见以下示例:
template < typename T >
struct A
{
};
// spezialize if needed, here only for demonstration purpose
template <> struct A<short> { void func(short parm) { std::cout << "A<short> with " << parm << std::endl; } };
template <> struct A<float> { void func(float parm) { std::cout << "A<float> with " << parm << std::endl; } };
class B
{
std::map<int, std::variant<A<short>*, A<float>*>> a;
public:
void AddA(int key, int type)
{
if (type == 1)
{
a.insert({ key, new A<short>() });
}
else
{
a.insert({ key, new A<float>() });
}
}
template<typename T>
void func(int key, T v)
{
std::visit( [&v]( auto ptr ) { ptr->func(v); }, a[key] );
}
};
int main()
{
B b;
b.AddA( 1, 1 );
b.AddA( 2, 2 );
b.func( 1, 99 );
b.func( 2, 100 );
}
我的header代码:
template <typename T>
class A
{
}
template<> class A<short>;
template<> class A<float>;
在我的cpp中,我想用一个map来包含不同类型的a,就像下面的代码:
class B
{
map<int, A*> a; /* how to declare a */
public:
AddA(int key, int type)
{
if (type == 1)
{
a.insert({ key, new A<short>() });
}
else
{
a.insert({ key, new A<float>() });
}
}
template<typename T>
func(int key, T v)
{
a[key].func(v);
}
};
提问:如何实现?
编辑@0410,这是我的解决方案:
class ABase
{
virtual void func(void* t)=0;
}
template <typename T> A;
template <short> A : public ABase
{
void func(void* t) override
{
auto value = *static_cast<short*>(t);
// do processing
}
template <float> A : public ABase
{
void func(void* t) override
{
auto value = *static_cast<float*>(t);
// do processing
}
CPP:为所有模板使用了 ABase* 映射 class,并为所有模板接口使用了虚函数
main()
{
map<int, ABase*> objs;
objs.insert({0, new A<short>()});
objs.insert({1, new A<float>()});
auto value=0;
objs[0]->func(&value);
auto value1=0.f;
objs[1]->func(&value1);
}
你不能用模板来解决问题。模板声明只是候选类型的蓝图。
“A
你可以通过继承来解决你的问题。
编辑:代码已根据@MSalters 的评论更新。谢谢
#include <iostream>
#include <map>
class A
{
public:
virtual void func(void* x) = 0;
};
class A_Short : public A
{
public:
void func(void* x)
{
short* value = static_cast<short*>(x);
std::cout << "short value: " << *value << std::endl;
}
};
class A_Float : public A
{
public:
void func(void* x)
{
float* value = static_cast<float*>(x);
std::cout << "float value: " << *value << std::endl;
}
};
template<typename T>
class A_Derived : public A
{
public:
void func(void* x)
{
T* value = static_cast<T*>(x);
std::cout << "[Derived] value: " << *value << std::endl;
}
};
class B
{
std::map<int, A*> a; /* how to declare a */
public:
void AddA(int key, int type)
{
if (type == 1)
{
a.insert({ key, new A_Short() });
}
else if(type == 2)
{
a.insert({key, new A_Derived<short>()});
}
else if(type == 3)
{
a.insert({key, new A_Derived<float>()});
}
else
{
a.insert({ key, new A_Float() });
}
}
// Assumes that user knows to use which T for any "key"
template<typename T>
void func(int key, T v)
{
a[key]->func(v);
}
};
int main()
{
B b;
b.AddA(1, 1);
b.AddA(2, 8);
b.AddA(3, 2);
b.AddA(4, 3);
short s = 1;
float f = 7.1;
short s2 = 2;
float f2 = 7.2;
b.func(1, &s);
b.func(2, &f);
b.func(3, &s2);
b.func(4, &f2);
}
如果你确实需要在一个地图中有多种类型,你可以使用std::variant
的地图。但是正如评论中已经提到的,这可能是一个设计问题。
但是如果你需要的话,你可以继续std::map< int, std::variant<>>
。稍后,如果你想访问存储的元素,你必须调用 std::visit
来选择存储在 std::variant
.
参见以下示例:
template < typename T >
struct A
{
};
// spezialize if needed, here only for demonstration purpose
template <> struct A<short> { void func(short parm) { std::cout << "A<short> with " << parm << std::endl; } };
template <> struct A<float> { void func(float parm) { std::cout << "A<float> with " << parm << std::endl; } };
class B
{
std::map<int, std::variant<A<short>*, A<float>*>> a;
public:
void AddA(int key, int type)
{
if (type == 1)
{
a.insert({ key, new A<short>() });
}
else
{
a.insert({ key, new A<float>() });
}
}
template<typename T>
void func(int key, T v)
{
std::visit( [&v]( auto ptr ) { ptr->func(v); }, a[key] );
}
};
int main()
{
B b;
b.AddA( 1, 1 );
b.AddA( 2, 2 );
b.func( 1, 99 );
b.func( 2, 100 );
}