c++ - Choose type of class members at run time
问题描述
I am trying to build a modular class containing other classes as members, where the user can specify the type of these classes at run time. I tried to implement this with templates, but realized that this is probably not the right approach. Here is a minimal working example:
#include <iostream>
// One of the modules. Code will consist of multiple of these modules.
template <class T, class U>
class Module1 {
public:
T subModule1;
U subModule2;
};
class Add {
public:
double Apply(double a) {
return a + x;
}
private:
double x = 2.5;
};
class Multiply {
public:
double Apply(double a) {
return a * pi;
}
private:
double pi = 3.14;
};
class Divide {
public:
double Apply(double a) {
return a / pi;
}
private:
double pi = 3.14;
};
int main(int argc, char* argv[])
{
// User input to determine the used submodules
// Here the user decides to use the Add and Multiply submodules.
Module1<Add, Multiply> module1;
std::cout << module1.subModule1.Apply(3) + module1.subModule2.Apply(2) << std::endl;
}
But how could I implement the decision which of the submodules should be used? E.g., if the user wants to use Divide and Add I have to create Module1 as
Module1<Divide, Add> module1;
There will be many different submodules, so branching the code with if's is also not be possible. I'm beginning to doubt this is possible with templates. Do you know a better way to accomplish this? Note that the implementation should also be very performant.
解决方案
Templates are used for compile-time polymorphism, while you want run-time polymorphism.
If you have a closed set of possible submodules, you can use std::variant
. It basically is a type-safe union
:
using SubmoduleVariant = std::variant<Add, Subtract, Multiply, Divide>;
class Module1 {
public:
SubmoduleVariant subModule1;
SubmoduleVariant subModule2;
};
// ...
Module1 m;
if(userInput == 0) { m.subModule1 = Add{}; }
else if(userInput == 1) { m.subModule1 = Subtract{}; }
else if(userInput == 2) { m.subModule1 = Multiply{}; }
else if(userInput == 3) { m.subModule1 = Divide{}; }
If you don't know the set of possible types in advance, but they all conform to the same interface, you can use virtual
functions and a base class.
If you don't know the set of possible types in advance, and they do not conform to the same interface, you can use std::any
, which is basically a wrapper over "an object of any type".
推荐阅读
- android - 如何使用 ViewModelProvider 获取扩展 AndroidViewModel 的自定义 ViewModel?
- docker - 挂载路径会在 Kubernetes 中创建一个新目录
- scala - 来自 spark shell 的 Hive 选择语句
- java - Spring Boot:在构造函数中加载属性文件并用作自动装配注释
- blockchain - 如何仅从保管库查询中获取数据
- javascript - 为什么我需要覆盖prototype.constructor 值?
- php - SQLSTATE [42S02]:未找到基表或视图:1146 表“fresh_start.event”不存在(SQL:从“事件”中选择计数(*)作为聚合)
- javascript - React/Redux,从模型调用方法抛出 TypeError
- ios - 如何在我的 UIPageViewController.swift 中添加另一个页面?
- google-cloud-platform - Swagger 文档位置不存在