Home > Mobile >  Is it possible to access a variable template without the template parameter?
Is it possible to access a variable template without the template parameter?

Time:11-06

I am not sure if this is viable. I want to initialize a variable template inside a constructor of my class.

template<typename T>
T var_tem;

Struct A {
  template<typename U>
  A(U u) { var_tem<U> = u;}
};

I am wondering if it's possible to access var_tem<U> later without knowing the type U. Also, I know whenever I access var_tem<>, only one instantiation exists. This would be much easier if I make my class hold var_tem as member data. But I have other methods I would rather not make templates due to issues discussed here section attribute of a function template is silently ignored in GCC. Basically, I have some internal static data needed to be emitted to a specific section.

CodePudding user response:

The information of the type U is not available after the call to constructor. However, at the point of access, you also need to be aware of the type, otherwise you wouldn't know what you can do with it. So either you specify the type directly, or you're passing a visitor.

Now, for visitors, as long as there's a compile-time limited set of signatures, it's doable. All you need is to enumerate these types and have a type switch (and store the pointer to the variable):

template<typename T>
T var_tem;

Struct A {
  template<typename U>
  A(U u)
  {
    var_tem<U> = u;
    var = &var_tem<U>;
  }

  void tryVisit() {}

  template<typename V, typename T, typename... Ts>
  void tryVisit(V& v)
  {
    if (var == &var_tem<T>) {
      v(*static_cast<T*>(var));
    } else {
      tryVisit<V, Ts...>(v);
    }
  }
    }
  }

private:
  void* var;
};

If listing the types is not an option, there's one more possibility, but it's only recommended for error handlers: you might throw it as an exception. Exception handlers are chainable, so you don't need a specific point at which you have all the possible types (but handlers are still listed on the stack). Note that you can only handle specific types this way, there are no template exception handlers. The throw function can then be stored as an std::function<void(void)>:

template<typename T>
T var_tem;

Struct A {
  template<typename U>
  A(U u)
  : throwTheVar([]() { throw var_tem<U>; })
  { var_tem<U> = u; }

  void throwAsError() { throwTheVar(); }

private:
  std::function<void()> throwTheVar;
};

If it's not an error handler, then I wouldn't suggest throw; but you might still populate a limited interface of std::function<>s using this lambda logic. The problem with it is that it's very slow: internally, std::function<> is either a virtual or a function pointer, depending on your implementation.

  • Related