Template parameter values must be known at compile-time. There is simple no way to directly convert a string at runtime to a type for use in a template parameter. You will have to compare the string value at runtime to decide which CreateDerivedClass specialization to call.
For instance, the simplest way to handle this is to use a std::map where its elements hold pointers to the specialized functions that you want to be able to call, eg:
using createFuncType = BasePtr (*)();
std::map<std::string, createFuncType> createFuncs;
createFuncs["D1"] = &CreateDerivedClass<D1>;
createFuncs["D2"] = &CreateDerivedClass<D2>;
...
Then you can do this:
std::string derived_names[] = {"D1", "D2"};
std::vector<BasePtr> derived_vec;
for (auto& name : derived_names) {
derived_vec.push_back(createFuncs[name]());
}
There is really no other option in this situation.
That being said, you should be using std::unique_ptr<Base> instead of raw Base* pointers, eg:
#include <map>
#include <vector>
#include <string>
#include <memory>
class Base {
public:
virtual ~Base() = default;
};
using BasePtr = std::unique_ptr<Base>;
using createFuncType = BasePtr (*)();
template<typename D>
BasePtr CreateDerivedClass() {
return std::make_unique<D>();
}
class D1 : public Base {
...
};
class D2 : public Base {
...
}
...
int main() {
std::map<std::string, createFuncType> createFuncs;
createFuncs["D1"] = &CreateDerivedClass<D1>;
createFuncs["D2"] = &CreateDerivedClass<D2>;
...
std::string derived_names = {"D1", "D2", ...};
std::vector<BasePtr> derived_vec;
for (auto& name : derived_names) {
derived_vec.push_back(createFuncs[name]());
}
...
return 0;
}
strtoul,std::istringstream. Since you didn't specify the type of variable, see alsostd::string::substr.