C++编译时模板多态性
C++ compile time template polymorphism
我想创建一个应用程序,在其中我可以定义键入问题的列表,然后迭代该列表并要求用户输入答案,将它们存储在另一个列表中,然后遍历答案,验证它们并提供结果。
我目前天真的做法是这样的:
class Question {
std::string message;
public:
Question(const std::string& msg) : message{msg} {}
std::string& getQuestion(void) const {
return this->message;
}
virtual ~Question(void) = 0;
};
Question::~Question(void) {}
template<class AnswerType>
class Prompt : public Question {
Prompt(std::string& msg) : Question{msg} {}
virtual ~Prompt(void) {}
};
class Answer<class T> {
T answ;
public:
Answer(const T& answer) : answ{answer} {}
T getAnswer(void) const {
return this->answ;
}
};
我想做一些类似的事情:
std::list< const Question* > whatToAsk{
new Prompt<int>{"Your age"},
new Prompt<std::string>{"Your name"},
new Prompt<float>{"Your weight"}
};
for(auto q in whatToAsk) {
Answer< "derived q template parameter" > a{};
std::cout << q->getQuestion() << ": ";
std::cin >> a;
// ... to be continued ...
}
将问题(Prompt<T>)存储在std::list<const问题*>。
但对我来说有问题的部分是,我必须使用下转换(带运行时检查)、虚拟函数(运行时多态性)或双重调度(同样带运行时开销)。
我担心的是,类型在编译过程中是已知的,因为问题列表将在源代码中进行硬编码,并且我希望避免运行时开销并实现编译时静态多态性。
我怎样才能做到这一点?也许是某种特征?
如果你不想使用虚拟函数/dynamic_cast
,你应该
- 把每个问题都做成不同的类型
- 将它们存储在元组中,而不是列表中
- 使用一个特殊的函数(
forEachArgument
——它可以在谷歌上搜索)进行迭代
使用虚拟函数做这件事要简单得多,除非你有成千上万的问题,否则运行时开销可以忽略不计。
我不是专家,但也许你可以使用c++11可变模板,这将允许你有一个不同类型的数组,因此不会因下变频而导致任何开销。
这个链接可能会让你感兴趣用可变模板创建静态数组
一些稀疏的音符,而不是一个回复
添加问题的答案处理部分成员函数。这样你就可以知道问题的类型。类似的东西
void ask()
{
Answer<T> answer ;
std::cint >> a ;
....
}
使用std::shared_ptr而不是普通指针。
也许一个被称为"问题工厂"的虚拟构造函数的习语可以帮助构建问题
类似的东西
Question *make_question(int type)
{
switch (type)
{
case 0: return new Prompt<int>() ;
case 1: return new Prompt<std::string>() ;
...
}
}
如果您使用的是c++14,您可以执行以下操作:
#include <iostream>
template <class FirstQuestion, class... OtherQuestions>
struct QuestionList {
template <class Functor>
void foreach(Functor &&functor) {
functor(FirstQuestion());
QuestionList<OtherQuestions...> oql;
oql.foreach(functor);
}
};
template <class FirstQuestion>
struct QuestionList<FirstQuestion> {
template <class Functor>
void foreach(Functor &&functor) {
functor(FirstQuestion());
}
};
template <class AnswerType, const char *QuestionString>
struct Question {
static AnswerType answer;
static void print_question() {
std::cout << QuestionString << std::endl;
}
static void get_answer() {
std::cin >> answer;
}
};
template <class AnswerType, const char *QuestionString>
AnswerType Question<AnswerType, QuestionString>::answer;
constexpr char questionstrings1[] = "lorem";
constexpr char questionstrings2[] = "ipsum";
int main() {
QuestionList<Question<int, questionstrings1>, Question<float, questionstrings2> > a;
a.foreach([](auto x){ x.print_question(); x.get_answer(); });
}
要在循环中访问答案,您可以简单地:
a.foreach([](auto x){ /*doing something with x.answer*/ };
PS意识到,提示用户回答会扼杀非运行时多态性的潜在效率。。。
相关文章:
- 多态性和功能结合
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- C ++中的方法覆盖:是编译时还是运行时多态性?
- 运行时与编译时多态性:更好的可读性与编译时错误检查,更重要的是
- 使用数组对对象的编译时多态性是否可行?
- 如果在编译时间中创建虚拟表,那么为什么我们将其称为运行时间多态性
- 编译时多态性运行时多态性是这样的吗
- C++编译时模板多态性
- 使用枚举编译时多态性
- 避免编译时已知类型的模板冗长和动态多态性
- 为什么不能在编译时解决运行时多态性?
- 如何实现几个函数的编译时多态性
- 尝试使用多态性C++时发生编译错误
- C++编译时多态性
- 编译时与运行时多态性在c++中的优缺点
- 允许运行时和编译时多态性的灵活方式
- 数据成员的编译时多态性
- 编译时多态性解决方案
- CRTP和动态多态性编译错误
- c++中运行时和编译时多态性的区别