-2

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.

max66
  • 65,235
  • 10
  • 71
  • 111
Mr George
  • 39
  • 7
  • 3
    What would be the key and value types (`T` and `N`) of the second `map`? –  Nov 25 '18 at 19:56
  • Well, you can specify default arguments, but you still need specify something if you want something else. – Matthieu Brucher Nov 25 '18 at 19:56
  • The terminology you're looking for is *template arguments*. They are not *constructor* arguments. – jamesdlin Nov 25 '18 at 19:59
  • @eukaryota It should be any primitive type. – Mr George Nov 25 '18 at 20:00
  • @MrGeorge Dynamically varying at runtime like `std::any`? (https://en.cppreference.com/w/cpp/utility/any) Or in the sense of compile-time fixed, but to be determined later after the construction? –  Nov 25 '18 at 20:02
  • @eukaryota If I understood correctly is compile-time fixed and determined later after the construction. For example, after the object map is created I should be able to do [map.Insert(any primitive type as the key, any primitive type as the value)]. I'm really sorry if I overcomplicate things but I'm fairly new in C++. – Mr George Nov 25 '18 at 20:09
  • @MrGeorge That's fine, I am just trying to figure out what you envision. Last question: In your idea, should it be possible to call `insert` one after another with different types, e.g. first `int/int`, then `string/string` or does the first call to insert determine the key and value type used? –  Nov 25 '18 at 20:14
  • @eukaryota It should be possible to call insert one after another with different types, even string/int or char/string. – Mr George Nov 25 '18 at 20:17
  • 1
    @MrGeorge In that case you should clarify this (best case by giving that example) in your question. The current answer for example does not consider this requirement. –  Nov 25 '18 at 20:19
  • If the goal is for the call to `MyCustomMap::Insert` to determine the types involved, then `MyCustomMap::Insert` should be a template function and `MyCustomMap` should not be a template. – Pete Becker Nov 25 '18 at 21:39
  • @PeteBecker If I do that, where do I initialize my keys and values? In the template function? – Mr George Nov 26 '18 at 13:37

1 Answers1

2

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.

max66
  • 65,235
  • 10
  • 71
  • 111