template typename question
I have a problem with template and wondering is there a possible way to achieve what I wanted to do. Here is my question.
template <typename T>
class A
{
public:
typedef T* pointer;
typedef const pointer const_pointer;
A()
{}
template <typename D>
A(const D& d)
{
// how can I store the D type
// so I can refer it later on
// outside of this function
}
};
ok here is a more complete code of what I wanted to do (it might not be compilable)
class C
{
public:
virtual ~C(){}
virtual void* get_d() = 0;
private:
};
template <typename T, typename D>
class Cimpl : public C
{
public:
Cimpl()
:t()
,d()
{}
Cimpl(const T& t, const D& d)
:t(t)
,(d)
{}
void* get_d()
{
return &reinterpret_cast<D&>(d);
}
private:
T t;
D d;
};
class B
{
public:
B()
:p(0)
{}
template <typename T, typename D>
B(const T& t, const D& d)
:p(0)
{
try
{
p = new Cimpl<T, D>(t, d);
}
catch(...)
{
d(p);
}
}
void* get_d()
{
return (p != 0) ? p->get_d() : 0;
}
~B()
{
delete p;
}
private:
C* p;
};
template <typename T>
class A
{
struct example_d
{
};
public:
typedef T* pointer;
typedef const pointer const_pointer;
A()
{}
template <typename D>
A(const T& t)
:b(t, example_d())
{
}
template <typename D>
A(const T& t, const D& d)
:b(t, d)
{
// how can I store the D type
// so I can refer it later on
// outside of this function
}
// not type safe...as user can cast to any type
// if I can store the type user pass in previous
// then I can use it back
template <typename T>
T* get_d()
{
reinterpret_cast<T*>(b.get_d());
}
private:
B b;
};
So I can use the class like
1)A<int> a(1);// with example_d as D
2)A<int> b(1, another_d()) // with another_d
I can change the template to take 2 parameters and use default parameter for 2nd type to be example_d. So I can achieve 1) but not 2). As I will have to code this way
A<int, another_d> b(1, another_d());
a bit to开发者_Go百科o long to type...
You cannot store a type, you can only store objects.
(If you want to store the parameter d
passed to A
's constructor, look at type erasure.)
You can't "save" a typename like that. What you really want to do is make type D one of the template parameters of the class, e.g.
template <typename T, typename D>
class A
{
public:
typedef T* pointer;
typedef const pointer const_pointer;
A()
{}
A(const D& d)
{
}
};
Now, if your problem is that you want A<T>
constructed with type D
to be polymorphic with A<T>
constructed with type E
instead of having A<T,D>
and A<T,E>
be two different types, then the solution is a base class:
template <typename T>
class ABase
{
public:
typedef T* pointer;
typedef const pointer const_pointer;
ABase()
{}
protected:
/* You might want to omit this constructor completely,
* depending on your use case */
template<typename D>
ABase(const D& d)
{
}
};
template <typename T, typename D>
class A : public ABase<T>
{
public:
A()
{}
A(const D& d)
: ABase(d)
{
}
};
This looks like you are trying to create a template class that has a boost::any member variable. You should look at this a possible way of doing this.
Basically a boost::any
can accept any value type. You can then retrieve that type safely if you know the type later. A good example of how you would use this is to store different datatypes in a map, (where you know the type later when you retrieve the the any by its name).
If this is not exactly what you are looking for the internals use a neat trick to implement it, and it will probably help you achieve what you are trying to do.
If you want to use type D in other member functions of class A, you can make D a second template parameter of class A.
精彩评论