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 too 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.
Related
Is it possible to safely cast between two function pointer in C++, given that the arguments as polymorphicly equivalent i.e. (example only)
class Base {}
class A : Base {}
class B : Base {}
class C : Base {}
template<typename T, typename U>
using FPTR = void (*)(const T&, const U&);
using index = std::pair<std:type_info, std::type_info>;
std::unordered_map<index, FPTR<Base, Base>> func_map;
template<typename T, typename U>
register(FPTR<T,U> fptr) {
// assert T and U are subclasses of Base
func_map[index(typeid(T), typeid(U))] = fptr;
}
void call(const Base& first, const Base& second) {
auto it = func_map.find(index(typeid(first), typeid(second)));
if (it != func_map.end()) {
(*it)(first, second)
}
}
void func1(const A&, const C&) {}
// call these
register<A,C>(func1);
register<B,B>([](const B&, const B&) -> void {});
so when invoking call, it would resolve the function to call based on the registered typeids, and the called function would expect the explicit type, effectively casting from the base type.
My thinking is this is going to cause an error at run time because the cast wron't occur correctly. I've considered using a lambda function to wrap fptr, but that would result in an extra indirect call, is there a way to avoid this while correctly performing the cast, note I can't cast in call, because I can only get the typeid/type_info and can't use that with the cast functions.
You can do it with an extra direct call, if that's not a problem (the target call might even be in-lineable in the wrapper, depending on your compiler and how the translation units are set up).
Something like:
struct Base {}
// ...
template <typename T, typename U>
using FPTR = void (*)(const T&, const U&);
template <typename T, typename U, FPTR<T,U> fptr>
void WrapFPTR(const Base &a, const Base &b)
{
fptr(static_cast<const T&>(a), static_cast<const U&>(b));
}
allows you to store WrapFPTR<T,U,foo> which is an FPTR<Base,Base> at every site where you register a given function foo.
If you really need an arbitrary function pointer, you'd need to store a polymorphic closure object with a pointer to that function's concrete type instead.
Current C++ contains no elaborate notion of co(ntra)variance. Can you go with static mapping instead?
#include <iostream>
class Base {};
class A : Base {};
class B : Base {};
class C : Base {};
template<typename T, typename U> using FPTR = void (*)(const T&, const U&);
// instead of allocating a run-time map, create a map on compiler's heap at compile-time
template<typename U, typename V> static FPTR<U const &, V const &> funcMap;
void nyan(A const &, A const &) { std::cout << "Nyan" << std::endl; }
void meow(B const &, B const &) { std::cout << "Meow" << std::endl; }
int main() {
funcMap<A, A> = nyan;
funcMap<B, B> = meow;
funcMap<A, A>(A{}, A{});
}
To implement a property system for polymorphic objects, I first declared the following structure:
enum class access_rights_t
{
NONE = 0,
READ = 1 << 0,
WRITE = 1 << 1,
READ_WRITE = READ | WRITE
};
struct property_format
{
type_index type;
string name;
access_rights_t access_rights;
};
So a property is defined with a type, a name and access rights (read-only, write-only or read-write). Then I started the property class as follows:
template<typename Base>
class property : property_format
{
public:
template<typename Derived, typename T>
using get_t = function<T(const Derived&)>;
template<typename Derived, typename T>
using set_t = function<void(Derived&, const T&)>;
private:
get_t<Base, any> get_f;
set_t<Base, any> set_f;
The property is associated to a base type, but may (and will) be filled with accessors associated to an instance of a derived type. The accessors will be encapsulated with functions accessing std::any objects on an instance of type Base. The get and set methods are declared as follows (type checking are not shown here to make the code minimal):
public:
template<typename T>
T get(const Base& b) const
{
return any_cast<T>(this->get_f(b));
}
template<typename T>
void set(Base& b, const T& value_)
{
this->set_f(b, any(value_));
}
Then the constructors (access rights are set to NONE to make the code minimal):
template<typename Derived, typename T>
property(
const string& name_,
get_t<Derived, T> get_,
set_t<Derived, T> set_ = nullptr
):
property_format{
typeid(T),
name_,
access_rights_t::NONE
},
get_f{caller<Derived, T>{get_}},
set_f{caller<Derived, T>{set_}}
{
}
template<typename Derived, typename T>
property(
const string& name_,
set_t<Derived, T> set_
):
property{
name_,
nullptr,
set_
}
{
}
The functions passed as arguments are encapsulated through the helper structure caller:
private:
template<typename Derived, typename T>
struct caller
{
get_t<Derived, T> get_f;
set_t<Derived, T> set_f;
caller(get_t<Derived, T> get_):
get_f{get_}
{
}
caller(set_t<Derived, T> set_):
set_f{set_}
{
}
any operator()(const Base& object_)
{
return any{
this->get_f(
static_cast<const Derived&>(object_)
)
};
}
void operator()(Base& object_, const any& value_)
{
this->set_f(
static_cast<Derived&>(object_),
any_cast<Value>(value_)
);
}
};
Now, considering these dummy classes.
struct foo
{
};
struct bar : foo
{
int i, j;
bar(int i_, int j_):
i{i_},
j{j_}
{
}
int get_i() const {return i;}
void set_i(const int& i_) { this->i = i_; }
};
I can write the following code:
int main()
{
// declare accessors through bar methods
property<foo>::get_t<bar, int> get_i = &bar::get_i;
property<foo>::set_t<bar, int> set_i = &bar::set_i;
// declare a read-write property
property<foo> p_i{"bar_i", get_i, set_i};
// declare a getter through a lambda
property<foo>::get_t<bar, int> get_j = [](const bar& b_){ return b_.j; };
// declare a read-only property
property<foo> p_j{"bar_j", get_j};
// dummy usage
bar b{42, 24};
foo& f = b;
cout << p_i.get<int>(f) << " " << p_j.get<int>(f) << endl;
p_i.set<int>(f, 43);
cout << p_i.get<int>(f) << endl;
}
My problem is that template type deduction doesn't allow me to declare a property directly passing the accessors as arguments, as in:
property<foo> p_i{"bar_i", &bar::get_i, &bar::set_i};
Which produces the following error:
prog.cc:62:5: note: template argument deduction/substitution failed:
prog.cc:149:50: note: mismatched types std::function<void(Type&, const Value&)> and int (bar::*)() const
property<foo> p_i{"bar_i", &bar::get_i, set_i};
Is there a way to address this problem while keeping the code "simple"?
A complete live example is available here.
std::function is a type erasure type. Type erasure types are not suitable for deduction.
template<typename Derived, typename T>
using get_t = function<T(const Derived&)>;
get_t is an alias to a type erasure type. Ditto.
Create traits classes:
template<class T>
struct gettor_traits : std::false_type {};
this will tell you if T is a valid gettor, and if so what its input and output types are. Similarly for settor_traits.
So
template<class T, class Derived>
struct gettor_traits< std::function<T(Derived const&)> >:
std::true_type
{
using return_type = T;
using argument_type = Derived;
};
template<class T, class Derived>
struct gettor_traits< T(Derived::*)() >:
std::true_type
{
using return_type = T;
using argument_type = Derived;
};
etc.
Now we got back to the property ctor:
template<class Gettor,
std::enable_if_t< gettor_traits<Gettor>{}, int> =0,
class T = typename gettor_traits<Gettor>::return_value,
class Derived = typename gettor_traits<Gettor>::argument_type
>
property(
const string& name_,
Gettor get_
):
property_format{
typeid(T),
name_,
access_rights_t::NONE
},
get_f{caller<Derived, T>{get_}},
nullptr
{
}
where we use SFINAE to ensure that our Gettor passes muster, and the traits class to extract the types we care about.
There is going to be lots of work here. But it is write-once work.
My preferred syntax in these cases would be:
std::cout << (f->*p_i)();
and
(f->*p_i)(7);
where the property acts like a member function pointer, or even
(f->*p_i) = 7;
std::cout << (f->*p_i);
where the property transparently acts like a member variable pointer.
In both cases, through overload of ->*, and in the second case via returning a pseudo-reference from ->*.
At the end of this answer is a slightly different approach. I will begin with the general problem though.
The problem is &bar::get_i is a function pointer to a member function while your alias is creating a function object which needs the class as additional template parameter.
Some examples:
Non member function:
#include <functional>
void a(int i) {};
void f(std::function<void(int)> func)
{
}
int main()
{
f(&a);
return 0;
}
This works fine. Now if I change a into a struct:
#include <functional>
struct A
{
void a(int i) {};
};
void f(std::function<void(int)> func)
{
}
int main()
{
f(std::function<void(int)>(&A::a));
return 0;
}
this gets the error:
error: no matching function for call to std::function<void(int)>::function(void (A::*)(int))'
because the std::function object also need the base class (as you do with your alias declaration)
You need a std::function<void(A,int)>
You cannot make your example much better though.
A way to make it a "bit" more easier than your example would maybe be this approach using CRTP.
#include <functional>
template <typename Class>
struct funcPtr
{
template <typename type>
using fun = std::function<void(Class,type)>;
};
struct A : public funcPtr<A>
{
void a(int i) {};
};
void f(A::fun<int> func)
{
};
int main()
{
f(A::fun<int>(&A::a));
return 0;
}
And each your "derived" classes derives from a funcPtr class which "auto generates" the specific alias declaration.
I have some conceptual problem in a class hierarchy, where the Base class depends on a fixed scalar type T, but the derived CRTP'ed classes use return value type deduction.
For example, consider the following class hierarchy:
template<typename ... Args> struct VectorBase;
template<typename T>
struct VectorBase<T>
{
virtual T eval(int) const = 0;
auto operator[](int i) {return this->eval(i);}
};
template<typename T, typename Derived>
struct VectorBase<T, Derived> : public VectorBase<T>
{
virtual T eval(int i) const override final { return this->operator[](i); }
auto operator[](int i) const
{
return static_cast<Derived const&>(*this).operator[](i);
}
};
template<typename T>
struct Vector : public VectorBase<T, Vector<T> >
{
//just for code shortness,
//in reality there is a container which returns the corresponding elements
auto operator[](int i) const { return T{}; }
};
template<typename VectorType>
struct SomeTransformation : public VectorBase< /* ... what to write here generically? */ double, SomeTransformation<VectorType> >
{
VectorType const& v;
SomeTransformation(VectorType const& _v) : v(_v) {}
auto operator[](int i) const
{
//do something with vector v and return i-th element, e.g.
return v[i]*0.1;
}
};
DEMO
Now, given a specific vector with value type int, say, one can apply SomeTransformation and get a vector of value type double. Moreover, I can be sure that SomeTransformation derives from VectorBase<double>, so that, for example, I can't falsely assign it to a VectorBase<int>-pointer:
int main()
{
Vector<int> v;
std::cout<<typeid(decltype(v[0])).name()<<std::endl; //prints "i" for int
auto u = SomeTransformation<decltype(v)>(v);
std::cout<<typeid(decltype(u[0])).name()<<std::endl; //prints "d" for double
//works
std::unique_ptr<VectorBase<double> > ud = std::make_unique<SomeTransformation<decltype(v)> >(v);
//gives a compile-time error, which is good
//std::unique_ptr<VectorBase<int> > ui = std::make_unique<SomeTransformation<decltype(v)> >(v);
}
Now for the problem: in the scalar type argument of SomeTransformation, where I wrote /* ... what to write here generically? */, I really would want to write something like
template<typename VectorType>
struct SomeTransformation :
public VectorBase<decltype(std::declval<SomeTransformation<VectorType> >().operator[](0)), SomeTransformation<VectorType> >
{
//...
};
in order to deduce the value type of the transformation automatically and propagate this type down to the base class. However, this doesn't seem to work, which I think is because the base classes are instantiated before the derived class ... so the class of which I want to deduce the type doesn't exists yet.
Is there any way to obtain this behaviour without breaking the inheritance hierarchy?
I figured out a possible alternative by myself and want to bring it up for discussion.
One could for instance add a type parameter T also to the derived class and then use a dummy type in order to instantiate this class once. With this, it is possible to deduce the return type of the so-created class, which is used in a next step to instantiate the class to be really used.
Example:
namespace detail
{
template<typename T, typename VectorType>
struct SomeTransformation :
public VectorBase<T, SomeTransformation<T, VectorType> >
{
//the same as above
};
}
struct DummyType
{
//make any type convertible to DummyType
template<typename T> DummyType(T const&) {}
};
template<typename VectorType>
using SomeTransformationValueType =
decltype(std::declval<detail::SomeTransformation<DummyType, VectorType> >().operator[](0));
template<typename VectorType>
using SomeTransformation =
typename detail::SomeTransformation<SomeTransformationValueType<VectorType>, VectorType>;
DEMO
So an A* pointer can point to any object having a base A, and a B* pointer can point to any object with a base B*. Is there anyway to make a pointer that can only point to objects that have both A and B as a base?
I'd also want it to be something I can store as a class member (perhaps a smart version) without making that class a template class.
Edit:
#KerrekSB asked below what the point of this is. Basically I want to make a number of pure virtual base classes (i.e. interfaces) say printable, flyable, something_else_able etc.
And then I might have a new class which requires in it's constructor requires something which is both printable and flyable. If it was just one or the other, you could store it as a (smart) pointer and let polymorphism take care of the rest, but I'm trying to work out how to do this if the class uses both bases.
Sure, you can use a type trait:
#include <type_traits>
template <typename T, typename A, typename B> struct has_two_bases
: std::integral_constant<bool, std::is_base_of<A, T>:: value &&
std::is_base_of<B, T>:: value> { }
Usage:
static_assert(has_two_bases<T, A, B>::value, "Not a good type");
T * p;
Does something like this fit the bill?
class W {};
class X {};
class Y {};
class Z : public X, public Y {};
template <typename A, typename B>
class DualPointer {
public:
template <typename T>
DualPointer(T *t) : a_ptr_(t), b_ptr_(t) {}
operator A*() { return a_ptr_; }
operator B*() { return b_ptr_; }
private:
A *a_ptr_;
B *b_ptr_;
};
int main() {
Z z;
DualPointer<X, Y> p(&z);
X *x = p;
Y *y = p;
return 0;
}
Or if you're in a C++11 mood:
template <typename... Ts>
class MultiPointer;
template <typename T, typename... Rest>
class MultiPointer<T, Rest...> : public MultiPointer<Rest...> {
public:
template <typename U>
MultiPointer(U *u) : MultiPointer<Rest...>(u), ptr_(u) {};
operator T*() { return ptr_; }
private:
T *ptr_;
};
template <>
class MultiPointer<> {
public:
MultiPointer(void *) {}
};
int main() {
Z z;
MultiPointer<X, Y> p(&z);
X *x = p;
Y *y = p;
return 0;
}
If you're worried about the double storage of pointers, this approach doesn't work. See comments below this answer as to why incorporating Paweł's suggestion of using a union, which works if and only if all the pointers are numerically identical (that is, there's no multiple inheritance or other shenanigans using adjusted this pointers going on), is unsafe and basically useless.
// DON'T USE THIS VARIANT!!!!
template <typename... Ts>
class MultiPointer {
public:
MultiPointer(void *) {}
};
template <typename T, typename... Rest>
class MultiPointer<T, Rest...> {
public:
template <typename U> MultiPointer(U *u) : rest_(u) { ptr_ = u; };
template <typename U> operator U*() const { return rest_; }
operator T*() const { return ptr_; }
private:
union {
T *ptr_;
MultiPointer<Rest...> rest_;
};
};
While you could write a pointer wrapper class (similar to "smart pointers", but not so smart in this case) which only accepts pointers to types derived from A and B, dereferencing them becomes ambiguous. This is a conceptual problem you can't solve with any method.
But you could provide two functions toA() and toB() and/or conversion operators in order to retrieve a pointer to one of the base classes. But as said, you can't (nicely) overload operator* to retrieve the base reference depending on the context (depending on whether an A* or a B* is needed in the context). Same with operator->.
template<typename A, typename B>
class DualPointer {
A *a; // We need two separate pointers because their distance is not known
B *b;
public:
template<typename T>
DualPointer(T* object) :
a(object),
b(object)
{ }
A *toA() const { return a; }
B *toB() const { return b; }
operator A* () const { return a; }
operator B* () const { return b; }
};
Using SFINAE you can also allow a function template which has the actual type as the template parameter, like to<MyBaseA>():
template<typename T>
typename std::enable_if<std::is_same<A, T>::value, T*>::type
to() {
return a;
}
template<typename T>
typename std::enable_if<std::is_same<B, T>::value, T*>::type
to() {
return b;
}
Demonstration of this wrapper class
You can then add such a pointer as a class member as requested in your question:
class MyClass {
DualPointer<MyBaseA, MyBaseB> pointer;
};
and access the pointer like:
pointer.toA()->memberFunctionOfA();
If your types A and B are fixed, then either drop the "template" line and replace A and B accordingly, or add a typedef DualPointer<MyBaseA, MyBaseB> MyAOrB;
Expanding on this, you could say one of the two base classes, say the first, is your "main" base class. That could then be the one the pointer acts like, so the one returned by operator* and operator->. The two operators would then look like:
A * operator-> () const { return a; }
A & operator* () const { return *a; }
Then the call from above can become as easy as
pointer->memberFunctionOfA();
but not simultaneously
pointer->memberFunctionOfB();
In C++, I'd like to be able to do the following:
struct IWrapper {
template<typename U>
U* dynamic_cast_to() { ??? } // what to do here?
};
template<typename T>
struct Wrapper : IWrapper {
Wrapper(T* _p) :p(_p) {}
T* p;
};
With this I'd like to be able to do
SomeDerived *a = new SomeDerived;
IWrapper *x = new Wrapper<SomeDerived>(a);
SomeBase *b = x->dynamic_cast_to<SomeBase>()
dynamic_cast_to() should return a pointer if indeed SomeDerived inherits from SomeBase and NULL if not, the same way normal dynamic_cast works.
Is this even possible?
give IWrapper a virtual destructor and use dynamic_cast.
i am amazed that the question is asked, how to implement a dynamic_cast_to function.
how can one avoid considering standard dynamic_cast then?
I don't think this can be done for arbitrary types T and U. The reason is that
the compiler has to generate the dynamic_cast code for the specific pair of types at compile time,
and there is no place where both types are known simultaneously at compile time.
If you could restrict IWrapper to just work for types derived from a certain base that had a virtual member function, then it could work like this:
struct IWrapper {
template<typename U>
U* dynamic_cast_to() { return dynamic_cast<U*>(commonBasePtr()); }
virtual CommonBase* commonBasePtr() = 0;
};
template<typename T>
struct Wrapper : IWrapper {
Wrapper(T* _p) :p(_p) {}
T* p;
virtual CommonBase* commonBasePtr() { return p; }
};
Not possible like that, because IWrapper doesn't know anything about T, nor has it access to the pointer. This should work:
template <typename T>
struct IWrapper {
IWrapper(T* p) : p_(p) {}
template<typename U>
U* dynamic_cast_to() { return dynamic_cast<U*>(p_); }
private:
T* p_;
};
template<typename T>
struct Wrapper : IWrapper<T> {
Wrapper(T* _p) : IWrapper<T>(_p), p(_p) {}
T* p;
};
struct SomeBase {
int a;
};
struct SomeDerived : public SomeBase {
int b;
};
int main()
{
SomeDerived *a = new SomeDerived;
IWrapper<SomeDerived> *x = new Wrapper<SomeDerived>(a);
SomeBase *b = x->dynamic_cast_to<SomeBase>();
return b->a;
}