Search code examples
c++classtemplatestemplate-argument-deduction

C++ How to create a class template that allows no template arguments


I apologize if my title is confusing. What I'm trying to do is create a class template implementing the std::map from scratch. What I want to achieve is to not use specific data types in the template arguments. Please see the code below:

#include "pch.h"
#include <iostream>
#include <string>

using namespace std;
template<typename T, typename N>

class MyCustomMap{
    public:
    MyCustomMap();
    T* keys;
    N* values;
};

template<typename T, typename N>
MyCustomMap<T, N>::MyCustomMap(){
    this->keys = new T[10];
    this->values = new N[10];
}
....
....
int main(){
    MyCustomMap<int,string> map; //This works because I specified the argument list
    MyCustomMap map; //This is my goal

    // The main goal is to call Insert one after another with different data types
    map.Insert(1, "Test");
    map.Insert("Test2", 2);

    return 0;
}

Is this possible? Any help is appreciated, thank you.


Solution

  • MyCustomMap map;

    Is this possible?

    Short answer: no.

    Long answer: if you pass some argument to the constructor

    MyCustomMap map{1, "one"};
    

    it's possible deduce int for T and char const [4] for V.

    But, unfortunately, only starting from C++17; give a look at this page for more informations.

    But if you don't pass arguments to constructor, there is no way to deduce arguments.

    EDIT

    The OP precise

    // The main goal is to call Insert one after another with different data types
    map.Insert(1, "Test");
    map.Insert("Test2", 2);
    

    Sorry: I've misunderstood your question.

    But the answer remain: no.

    C++ is a compiled and strongly typed language.

    And a template class isn't a class: is a set of classes.

    When you instantiate an object

    MyCustomMap map;
    

    this object (map, in this case) must be a an object of a precise type; known to the compiler at compile time in that precise position.

    So you can't instantiate a map of type, generally, MyCustomMap. You must choose a couple of types. Maybe with default values, maybe deducing type through constructor arguments, maybe using the auto type and using the type returned by a function, but you must choose the type when you declare the variable. Not after.

    And, anyway, if you want

    map.Insert(1, "Test");  
    map.Insert("Test2", 2);
    

    you want an object that is, contemporary, of two different types.

    There is something in this direction, in C++17: look for std::any and std::variant. But not so flexible.