大家好
想问大家,如果我有这样的伪代码:
// 基类
classA {
}
template <typename T>
derived classB: A {
}
template <typename T>
derived classD: A {
}
class C {
public:
auto create_members() ->int {}
auto get_member(int id) -> *A {}
auto do_something(int id1,int id2)-> void{}
private:
std::vector<std::unique_ptr<classA>> members;
}
已知在main function里面,我们定义了:
auto b = new classB();
auto c = new classD<std::tuple<int, double>>();
然后,比如在这个classC::do_something的函数中,
A* a1 = get_number(id1)
A* a2 = get_number(id2)
我的问题是:有没有什么办法能知道在main function中定义的b的type是什么?比如auto b = new classB(),我想在classC中得到这个type是int。。然后c的type是std::tuple<int, double>...然后再比较b的type是否存在与c这个tuple的type里面。。。
因为在classC中不会知道用户在主函数中定义了什么classB<>,它可以是classB,classB或者classB<std::tuple<int, double>>,我真的很懵逼
谢谢大家
你如果需要到class C里去判断到底是什么类型,那你用继承和泛型就完全是多此一举了
到头来还是要写一堆if,else
你在设计这个类的时候就要考虑到不管它是个什么类型,操作都应该是一致的
如果两个类之间的操作没有一致性,那么它就不应该继承同一个基类,没意义
可以使用类型萃取技术获取真实类型。具体来说,可以使用std::is_specialization模板来判断一个类是否为另一个类的特化版本,然后使用std::tuple_element模板来获取std::tuple中的元素类型。下面是一个可能的实现:
#include <tuple>
#include <type_traits>
template <typename T>
struct is_specialization : std::false_type {};
template <template <typename...> class Template, typename... Args>
struct is_specialization<Template<Args...>> : std::true_type {};
class A {};
template <typename T>
class B : public A {};
template <typename T>
class D : public A {};
class C {
public:
auto create_members() -> int {}
auto get_member(int id) -> A* {}
auto do_something(int id1, int id2) -> void {
A* a1 = get_member(id1);
A* a2 = get_member(id2);
if (is_specialization<B>(a1) && is_specialization<D>(a2)) {
using T = typename std::tuple_element_t<0, typename B<int>::template type<T>::type>;
using U = typename std::tuple_element_t<0, typename D<T>::template type<T>::type>;
static_assert(std::is_same_v<T, int>, "B must be specialized with int");
static_assert(std::is_same_v<U, double>, "D must be specialized with std::tuple<int, double>");
// do something with a1 and a2
}
}
private:
std::vector<std::unique_ptr<A>> members;
};
template <typename T>
struct type {};
int main() {
auto b = new B<int>();
auto c = new D<std::tuple<int, double>>();
C c_obj;
c_obj.do_something(0, 1);
return 0;
}
在这个实现中,我们使用了一个辅助结构体type来获取类的真实类型。我们假设B和D都是特化版本,然后使用std::tuple_element来获取B和D中的模板参数类型,然后进行类型比较。如果B被特化为int,D被特化为std::tuple<int, double>,则可以进行后续操作。注意,这里使用了typename关键字来告诉编译器type::type是一个类型。此外,还需要注意模板特化的语法,即typename Template<Args...>::template type这种形式。