gpt4 book ai didi

c++ - 模板类对象的数组

转载 作者:行者123 更新时间:2023-12-02 10:09:20 25 4
gpt4 key购买 nike

问题
我想要一组指向模板类实例的指针。如果C++允许基类中带有模板派生类的模板虚拟方法可以解决我的问题。
因此,如何实现模板化虚拟方法?
下面,我有一个似乎可行的解决方案,但我对自己的实现方式感兴趣。
约束
template参数是无限可变的,例如,我无法枚举此模板类的每个特殊化。模板类T可以是任何POD,POD数组或POD的结构。
完整的T集合在编译时是已知的。基本上,我有一个文件,该文件定义了用于实例化对象的所有不同T,并使用Xmacros(https://en.wikipedia.org/wiki/X_Macro)创建对象数组。
我知道这不是一个好主意。让我们暂时忽略一下。最终变得更加好奇。
可能的解决方案
这些是我研究过的东西。
创建基类和派生类

class Base {
virtual void SomeMethod() = 0;
}

template <class T>
class Derived : Base {
void SomeMethod() {...}
}
问题是我无法在 Base中声明要重载的所有虚拟方法,因为无法对虚拟方法进行模板化。否则,这将是一个完美的解决方案。
std::any / std::variant
我正在使用C++ 17,因此可以使用 std::any定义虚拟基本方法。但是它不能保存数组,因此无法在此处使用。
CRTP
看来这无助于我创建这些不同对象的数组。我需要做类似的事情
template <typename D, typename T>
class Base
{
...
};

template <typename T>
class Derived : public Base<Derived, T>
{
...
};
因此,我仍然最终尝试创建一个 Derived<T>对象数组。
访客模式
再次看起来,我需要枚举 Visitable类需要服务的每种可能的类型,尽管并非不可能(再次,我有一个文件定义了将要使用的所有不同的 T),但看起来像更多的Xmacros,这仅仅是使问题更加复杂。
我的解决方案
这就是我想出的。它将在 https://www.onlinegdb.com/online_c++_compiler中运行
#include <iostream>
#include <array>
#include <typeinfo>

// Base class which declares "overloaded" methods without implementation
class Base {
public:
template <class T>
void Set(T inval);
template <class T>
void Get(T* retval);
virtual void Print() = 0;
};

// Template class which implements the overloaded methods
template <class T>
class Derived : public Base {
public:
void Set(T inval) {
storage = inval;
}
void Get(T* retval) {
*retval = storage;
}
void Print() {
std::cout << "This variable is type " << typeid(T).name() <<
", value: " << storage << std::endl;
}
private:
T storage = {};
};

// Manually pointing base overloads to template methods
template <class T> void Base::Set(T inval) {
static_cast<Derived<T>*>(this)->Set(inval);
}
template <class T> void Base::Get(T* retval) {
std::cout << "CALLED THROUGH BASE!" << std::endl;
static_cast<Derived<T>*>(this)->Get(retval);
}

int main()
{
// Two new objects
Derived<int>* ptr_int = new Derived<int>();
Derived<double>* ptr_dbl = new Derived<double>();

// Base pointer array
std::array<Base*, 2> ptr_arr;
ptr_arr[0] = ptr_int;
ptr_arr[1] = ptr_dbl;

// Load values into objects through calls to Base methods
ptr_arr[0]->Set(3);
ptr_arr[1]->Set(3.14);

// Call true virtual Print() method
for (auto& ptr : ptr_arr) ptr->Print();

// Read out the values
int var_int;
double var_dbl;
std::cout << "First calling Get() method through true pointer." << std::endl;
ptr_int->Get(&var_int);
ptr_dbl->Get(&var_dbl);
std::cout << "Direct values: " << var_int << ", " << var_dbl << std::endl;
std::cout << "Now calling Get() method through base pointer." << std::endl;
ptr_arr[0]->Get(&var_int);
ptr_arr[1]->Get(&var_dbl);
std::cout << "Base values: " << var_int << ", " << var_dbl << std::endl;

return 0;
}

运行此命令时,表明在 Base上调用方法正确指向 Derived实现。
This variable is type i, value: 3                                                                                                    
This variable is type d, value: 3.14
First calling Get() method through true pointer.
Direct values: 3, 3.14
Now calling Get() method through base pointer.
CALLED THROUGH BASE!
CALLED THROUGH BASE!
Base values: 3, 3.14
本质上,我是在手动创建虚拟方法指针。但是,由于我明确地这样做了,因此可以使用 Base中的模板方法,该模板方法指向 Derived中的方法。它更容易出错,例如,对于每个模板方法,我需要两次键入方法名称,即,我可能会弄乱:
template <class T> void Base::BLAH_SOMETHING(T inval) {
static_cast<Derived<T>*>(this)->WHOOPS_WRONG_CALL(inval);
}
毕竟,这是一个可怕的主意吗?对我来说,这似乎可以达到我避免模板化虚拟方法局限性的目标。这真的有什么问题吗?我了解可能存在构建代码的方法,这些方法使所有这些事情都不必要,我只是专注于这种特定的结构。

最佳答案

It is more prone to error, as for example for each template method I need to type the method name twice


哦,那是您最不用担心的。想象一下,如果您将类型转换为错误的类型。
至少可以避免头痛,并使用 dynamic_cast:
class Base {
public:
virtual ~Base() = default;

template <class T>
void Set(T inval) {
dynamic_cast<Derived<T>&>(*this).Set(inval);
}

template <class T>
T Get() {
return dynamic_cast<Derived<T>&>(*this).Get();
}
};


template <class T>
class Derived : public Base {
public:
void Set(T inval) {
storage = inval;
}

T Get() {
return storage;
}

private:
T storage{};
};
除此之外,我同意这些意见,这可能不是解决您问题的正确方法。

关于c++ - 模板类对象的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64269298/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com