Search code examples
c++templatestype-safety

Combining templates and type safety


Let's say I have several functions defined like this:

template <typename T>
inline void read<bool>(T **data) {
    //some code
}

template <typename T>
inline void read<double>(T **data) {
    //some other code
}

template <typename T>
inline void read<int>(T **data) {
    //also different code
}

Now, I create another function defined like this:

template<typename T>
inline void readMultiple(T **data, int counter) {
    for (int i = 0; i < counter, ++i) {
       read<T>(data);
    }
}

(1)That would call the appropriate read<T>(T **data) implementation based on the type T, right?

(2)If I were to specify a type that is not one of the three above, I'd get a compilation error, since that function is not defined, right?

(3)Also, can I make this call:

double **d;
read<double>(d);

to ensure that I called the implementation for double?

I know I'd get the same result without the <double> part, but this way I'm ensuring that double is passed to the function, where as doing it without <double> would allow for d to be a int or a bool and the code would still compile, silently introducing an error.


Solution

  • (1)That would call the appropriate read<T>(T **data) implementation based on the type T, right?

    Yes, assuming the specializations are visible at the point where read<T>(data) is encountered.

    (2)If I were to specify a type that is not one of the three above, I'd get a compilation error, since that function is not defined, right?

    You haven't provided your declaration of the template read() function, so this can't be answered. Assuming that you have declared it like template <typename T> void read(T**); and have not defined it anywhere then yes, you would get a link-time error when the linker is unable to find an implementation of the requested specialization.

    (3)Also, can I make this call:

    double **d;
    read<double>(d);
    

    to ensure that I called the implementation for double?

    You can, though <double> is superfluous and will be inferred.

    ... silently introducing an error.

    If the thing you're passing is a bool** then it would not be an error to use the bool specialization. I don't really see any benefit from explicitly providing the template arguments. If bool** is the wrong type then presumably you would be getting errors somewhere else, anyway.

    I guess it depends on what you mean by "silently introducing an error." It's not clear what kind of error you're trying to prevent. I can come up with a contrived example, but contrived examples rarely represent real-world dangers.


    Two side notes:

    1. The syntax for your specializations is incorrect. It should be template <> inline void read<bool>(bool **data) { /* ... */ } for example.
    2. There's no need for templates here at all, you can just have three function overloads. Having an undefined template function with explicit specializations is an anti-pattern; overloads are the recommended way to implement the same thing.