1

Is it possible to define a class which is not a class template and that can store (say upon construction) a reference to any particular type and retrieve it later via a getter method?

struct Wrapper {
  template<typename T> Wrapper(const T& t): t_(t);

  // How to store the reference??
};

Boost::variant is of course not a solution since its implemented as a class template. And I have no RTTI. (Its in HPC environment, performance is all!)

The getter() should be able to remember the type. So that auto can be used later.

ritter
  • 7,447
  • 7
  • 51
  • 84

2 Answers2

5

The getter() should be able to remember the type.

It can't. You erased the type. That's what happens when you put a value of arbitrary type inside an object of a consistent type. It's called "type erasure": the original type is removed from the containing class.

One of the consequences of this is that the type cannot magically be recovered. You can't have a class that is initialized with a type on a per-instance basis, and then have one of its member functions return a different type based on how that particular instance was initialized.

C++ is a statically typed language. The return type of every function must be defined at compile time. It cannot change because of what you put into a class at runtime.

It can't remember the type.

I can't use RTTI.

Then what you want is a void*. RTTI is the only way to do recover the original value's type in a type-safe way. If you don't want type-safety, then you want a void*. All you would be doing is writing a wrapper around static_cast<T*>.

There's really no point in writing a wrapper around void* and static_cast. If that's what you want, and you're willing to accept the perils of using them (ie: breaking the type-system), then just use it. The reason boost::any exists is to provide a type-safe void*, so that at least you know when you're casting it wrongly.

Community
  • 1
  • 1
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
3

boost::any http://www.boost.org/doc/libs/1_50_0/doc/html/any.html

std::vector<boost::any> many;
int i = 5;
std::string a = "5";

many.push_back(i);
many.push_back(a);

std::string res;
if (many[1].type() == typeid(std::string))
  res = boost::any_cast<std::string>(many[1]);
log0
  • 10,489
  • 4
  • 28
  • 62
  • 2
    Well anyhow you have to remember the type of what you are putting in your wrapper. Either you store its RTTI like with boost any, either you are using a union and remember which representation is correct like with boost variant... But maybe we are missing your real problem. You said you want a simple return type to `operator+`. What is the problem exactly ? – log0 Aug 04 '12 at 19:50
  • @Frank Note that the cost of using typeid is light in c++. It is a constant time operation if the type is polymorphic, and has no cost if the real type can be deduced directly or indirectly at compile time. http://en.cppreference.com/w/cpp/language/typeid – log0 Aug 05 '12 at 09:56