有没有办法提示用户使用哪种数据类型作为模板 c++

Is there a way to prompt user what data type to use as template c++

本文关键字:数据类型 c++ 提示 用户 有没有      更新时间:2023-10-16

我正在制作一个简单的带有动态内存和模板的双向链表,它应该接收用户输入以生成它。 现在我想提示用户列表是由整数、浮点数、双精度还是字符组成的。这可能吗?

template <class T>
class le
{
nodo<T>* head = nullptr;
bool (*comp)(T, T);
public:
le(bool (*c)(T, T) = ascendente) {
comp = c;
}
void add(T valor);
void remove(T valor);
bool find(T bus, nodo<T>*& pos);
void print();
~le();
};

我坚持的一种选择是为每个数据类型声明 4 个列表并为每个列表创建一个指针,但如果有直接的方法可以做到这一点,它将节省内存并且会更快。

le<int> leInt;
le<char> leChar;
le<float> leInt;
le<double> leChar;

处理此问题的最直接方法是使用适配器模式,其中适配器都继承自"接口"类型(仅限纯虚拟方法(。 为此,您需要知道需要对每个列表执行哪些调整操作。

例如,给定单个操作"将项目添加到列表",我们可以使用std::string作为参数类型,因为这无论如何都可能是输入类型。 因此,我们的基本适配器接口如下所示:

class le_adapter {
public:
virtual ~le_adapter() = default;
virtual bool add(std::string const &) = 0;
};

现在我们需要为每个列表类型实现适配器。 值得庆幸的是,模板可以在这里帮助我们:

template <typename T>
class le_adapter_impl : public le_adapter {
public:
virtual bool add(std::string const &) override;
le<T> & get();
private:
le<T> list;
};
template <typename T>
bool le_adapter_impl<T>::add(std::string const & str) {
// Naive implementation; should do more error checking.
T value;
std::istringstream source{str};
if (source >> value) {
list.add(value);
return true;
}
return false;
}
template <typename T>
le<T> & le_adapter_impl<T>::get() {
return list;
}

现在我们有一个适配器,我们可以放在给定类型的列表前面,并通过le_adapter多态地使用它,而无需知道其中包含哪种列表。 (请注意,"适当的"适配器将存储引用/指针而不是对象,但让适配器拥有列表可以简化此示例。

现在,您可以根据用户的输入构造不同的适配器。 例如,您可以将工厂函数存储在映射中:

std::map<std::string, std::function<std::unique_ptr<le_adapter>()>> factories{
{"int", std::make_unique<le_adapter_impl<int>>},
{"char", std::make_unique<le_adapter_impl<char>>},
{"float", std::make_unique<le_adapter_impl<float>>},
{"double", std::make_unique<le_adapter_impl<double>>},
};

现在,您有一个地图,可用于根据用户输入的内容分配适配器:

std::string input{"int"}; // Example user input
auto i = factories.find(input);
if (i != factories.end()) {
auto adapter = i->second(); // Creates the desired adapter.
adapter->add("123"); // This would also be user input
} else {
// Handle invalid selection
}

现在我们有adapter这是std::unique_ptr<le_adapter>. 您不必知道使用哪个特定的实现即可使用基本接口上定义的虚拟方法。

适配器仅与其基本接口一样有用;如果需要支持其他操作,则必须在该接口上定义它们,并且它们必须具有泛型参数或返回值才能有用。

如果您需要执行广泛的操作/计算,这将受益于了解T的类型,那么您可以使用模板函数并通过重载函子使用访问者模式将其应用于适配器。 (或者在适配器中作弊并执行此操作,尽管这可能被视为违反关注点分离。

模板参数必须在编译时计算,而用户输入发生在运行时,因此没有直接的方法基于用户输入指定模板。

您需要在代码中显式指定模板化类的多个版本 - 无论是作为单独声明的变量、分配公共指针的单独语句,还是具有其他间接级别,然后可以根据用户输入进行选择。

你可以通过编写这样的帮助程序函数来做你想做的事情。

template <typename T>
void do_work() {
le<T> list;
// do stuff
}
int main() {
if(use_double) {
do_work<double>();
}
else if(use_int) {
do_work<int>();
}
}

显然,您需要将main中的虚拟逻辑替换为用于从用户处获取类型的任何逻辑。 由于实际逻辑是do_work的,并且您现在有一个特定的类型(T(,因此您不需要多个le实例浮动。 这也意味着您可以通过使用新类型调用do_work来添加新类型(例如,do_work<le<int>>,如果你想要一个整数列表

(。