Search code examples
c++stringtemplatesusingtypename

Can you use a string(or c string) as a typename


I have a map loading function that takes input using ifstream from a file and creates objects from them.

Here is what the file might look like:

tree=50,100,"assets/tree.png"
box=10,10,"assets/box.png"

Which should create the objects tree and box and pass the values to their constructor. I already have the value part figured out, but I don't know how to take the string "tree" and create a tree object.

Is it possible to take a string(or c string) and use it as a type name?

Things I've tried:

  • Passing the string as a template typename

    #include <string>
    
    struct A {};
    
    template<typename T>
    T* createType() {
        T* type = new T()
        return T;
    }
    
    int main() {
        std::string tname = "A";
        auto* type = createType<tname>;
    }
    
  • Using the using keyword

    #include <string>
    
    template<std::string T>
    struct someType {}
    
    struct A {};
    struct B {};
    
    using someType<"A"> = A;
    using someType<"B"> = B;
    
    int main() {
        std::string tname1 = "A";
        std::string tname2 = "B";
        someType<tname1> typeA;
        someType<tname2> typeB;
    }
    

Problems:

  • I can't seem to find a clear answer about this but is seems like there are some problems with using a string as a template parameter.

  • I don't know if it is ok to pass a variable as a template parameter

  • I don't think that you can cast template types (from string to typename)

Is there any way that either of these, or some other way might work to accomplish this? Or is this just not possible?


Solution

  • No. As far as I know, there is no provision in C++ for finding types from an in-language string of any kind.

    As for your other problems:

    • A value template parameter must be constexpr: since C++11, you can use variables of some constexpr types as template parameters
    • Apparently you can use a constexpr string_view template parameter in C++17, and a constexpr string template parameter in C++20

    Regardless of these other answers, you still can't turn those strings into types. That kind of operation is typical of dynamic languages, but C++ is a statically typed, compiled language. And, while it is possible to design a static language that can do that kind of operation at compile time, that is not the path that C++ design has taken.

    I think it's reasonable to ask: why you want to do this in the first place? There is probably a better way to accomplish whatever prompted the question, but without further information it is hard to know how to help.


    Edit, in response to updated question:

    In order to read datastructures from a file, you will need do the string-to-type mapping yourself.

    Generally, you will have some "driver" object where you register types that you want to create from your file, which it will then use when reading from the file.

    The simplest way is to register each typename in association with a callback to construct the data. The most straightforward, object-oriented way to handle the resulting heterogeneous datastructures is to derive all their types from a common Readable base class.

    Registration is where you will provide the typename to be used in the file. If you don't feel like repeating the typename with every registration line, you can use macros to do that -- something like:

    #define REGISTER(type) (driver.register(#type, &(type)::construct))
    

    (note that #name is the C preprocessor's "string-izing" syntax)