0

I am trying to build a structure in C++ that holds classes as keys and has ints as values. I would like to have this a sort of static map, which I can then use in my program to access the int associated to a certain class easily.

This is the code that I am trying to write:

#include <unordered_map>
#include <typeindex>
#include <typeinfo>
#include "TransformC.h"

// map class -> int
std::unordered_map<std::type_index, int> comp_cols;
// populate map
comp_cols[std::type_index(typeid(TransformC))] = 0;
...

I am on Visual Studio 2017 and I get an "expression must have a constant value" error squiggle at std::type_index.

I don't understand what exactly that error is about, and I don't know whether there are other ways of achieving what I am trying to achieve (maybe some template shenanigans that substitutes at compile time a map<Class> with the right index?)

I get this error only if the code posted above is in file scope (I don't have the error in function scope). I can't understand why the error is there in one case and not in the other one.

Please help!

Michele Piccolini
  • 2,634
  • 16
  • 29
  • You mean that `comp_cols[std::type_index(typeid(TransformC))] = 0;` line is placed outside of any function? That will not work. – Yksisarvinen Oct 04 '19 at 20:01
  • You can't run arbitrary code in the global space. You can only define/declare things there. – NathanOliver Oct 04 '19 at 20:03
  • Thanks. Then my question becomes: can't I write code that executes at compile time outside of any function? And how to write something like the static mapping I want to achieve? – Michele Piccolini Oct 04 '19 at 20:05
  • @MichelePiccolini You do that when initializing. You would use something like – NathanOliver Oct 04 '19 at 20:06
  • `std::unordered_map comp_cols = {{std::type_index(typeid(TransformC)), some_value}, {std::type_index(typeid(other_type)), other_value}, ... };` – NathanOliver Oct 04 '19 at 20:07
  • @NathanOliver ok please help me understand. The issue here is entirely due to trying to execute a statement (assignment) at global scope, while initializing when defining the object is allowed? But doing this at global scope is not necessary, since doing that somewhere during initialization would achieve the same result? I am struggling to understand the order in which each part of that code is executed. Is typeid(...) evaluated at compile time? Is std::type_index too? – Michele Piccolini Oct 04 '19 at 20:20
  • 1
    *The issue here is entirely due to trying to execute a statement (assignment) at global scope, while initializing when defining the object is allowed?* Correct. You can define and initialize variable in the global space. You can't define and the assign to a variable in the global space. I think your major confusion is you think all variables have to be initialized at compile time. This is not the case. We just need to know what the initializer is. `std::unordered_map` can only be initialized at run time since it needs to allocate memory. – NathanOliver Oct 04 '19 at 20:25
  • This means you initialization expression is "saved" into the program and will be executed once the program starts. – NathanOliver Oct 04 '19 at 20:25
  • Also, when I later on query the map: `some_value = comp_cols[std::type_index(typeid(TransformC)];`, is that evaluated at run time? Or substituted at compile time? I am searching for something that gives me numbers from the map at compile time, but has the interface of a function, instead of going for `#define TRANSFORM_C_ID 0 ...` – Michele Piccolini Oct 04 '19 at 20:25
  • You can't access a `std::unordered_map` at compile time so this whole solution is a no go. – NathanOliver Oct 04 '19 at 20:26

0 Answers0