AFAIK, a template class with template argument <Type> is completely distinct from <const Type>.
template<typename T>
struct Wrapper
{
T obj = T{};
//other code
};
Now I can't pass Wrapper<int>& to a function that needs Wrapper<const int>&.
void someFunc(Wrapper<const int>& wrapper);
//...
Wrapper<int> wrapper;
someFunc(wrapper); //error
What can go wrong by reinterpret_cast'ing it to its const version?
operator Wrapper<const T>&() { return *(reinterpret_cast<Wrapper<const T>*>(this)); }
Adding the above line to Wrapper makes it work without having to create a new <const int> object. obj can't be accessed inside the function, so it should not matter if the passed parameter is actually <const Type> or <Type>.
Provided there is no template specialization, can anything go wrong here (as far as standard goes vs in practice)?
There is a number of optimizations that can be different between the const and non-const cases, meaning both the memory layout of the class (e.g. since const objects does not need to actually exist) and the usage of the class can be different.
In other words: Using reinterpret_cast for this can result in unexpected behaviour and should not be done.
In my opinion there are several ways where over-eager usage of the const keyword can result in more complicated code without any gain, and this is one of them.
I suggest avoiding the <const Type> cases instead of trying to handle them.
Without knowing the use case, it seems to me most use cases would be covered by using const Wrapper<T> instead of Wrapper<const T>.
Related
I went through some searches but couldn't quite find this one. Consider this situation:
template <class T> class TemplClass;
void a_function(TemplClass<const X>&);
TemplClass<X> inst;
a_function( inst ); // fails
"invalid initialization of reference of type ‘TemplClass&’ from expression of type ‘TemplClass’"
The situation is 100% safe as far as I can tell. Still, C++ does not allow this. So I wonder what cast to use instead of the trivial C-cast.
a_function( static_cast<TemplClass<const X>&>(inst) ); // fails, similar error message
a_function( reinterpret_cast<TemplClass<const X>&>(inst) ); // works
dynamic_cast is out of the question, const_cast fails too (and rightly so).
The reinterpret_cast feels fishy (is it though?). But is there a solution with some kind of trick that I missed? Anyone know why the standard does not simply detect that this is something good? Or is there something 'bad' about this cast?
TemplClass<const T> and TemplClass<T> are unrelated types.
For example you may have (partial) specialization to make them really different:
template<typename T>
class TemplClass
{
void generic();
std::string s;
};
template<typename T>
class TemplClass<const T>
{
void foo();
std::vector<int> v;
};
Casting one into the other doesn't make sense.
In the same way
class A
{
char* p;
};
class B
{
char* p;
};
Those 2 classes are unrelated (even if it seems identical).
But is there a solution with some kind of trick that I missed?
The ideal solution is to not write such restricted template interfaces. For example, consider the standard library algorithms that take iterators to represent ranges rather than specific template types with specific object types.
If you're unable to fix the interface as it's say in a third party library, then you're going to be stuck copying your Templ<X> to a Templ<const X> before making the call.
Anyone know why the standard does not simply detect that this is
something good?
Because it's not good. The very simplest case is where there are template specializations where it would change some meaning/functionality. The compiler can't simply change the instantiation of the template.
Or is there something 'bad' about this cast?
By the language, the cast is illegal because the const and non-const template instantiations are unrelated types. Depending on the actual case, there are probably legal alternatives.
I have this template method:
template <class SomeLhs, class SomeRhs,
ResultType (SomeLhs::*callback)(SomeRhs&)>
void Add() {
struct Local {
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs) {
return (static_cast<SomeLhs&>(lhs).*callback)(static_cast<SomeRhs&>(rhs));
}
};
_back_end.template Add<SomeLhs,SomeRhs>(&Local::Trampoline);
}
Currently I'm calling it like this:
tracker.Add<Quad, Multi, &Quad::track>();
tracker.Add<Quad, Singl, &Quad::track>();
tracker.Add<Sext, Multi, &Sext::track>();
...
It is working fine, but I don't like to have to repeat two times the name of class SomeLhs. Is there a way to avoid that?
For people who may have recognized it: yes, this is related to the BasicFastDispatcher of Alexandrescu, in particular I'm writing a front end to operate with member functions.
I don't think it can't be improved particularly, which is unfortunate as I'd love to find a way to do this.
Template type deduction is only possible for function template arguments and you need to pass in the non-type member function pointer at compile time in order for it to be treated as a name rather than a varying quantity. Which means having to specify all the args.
i.e. you can do this:
template <class SomeLhs, class SomeRhs>
void Add(ResultType (SomeLhs::*callback)(SomeRhs&)) {
...
}
// nice syntax:
tracker.Add(&Sext::track);
// But ugly for overloaded functions, a cast is needed.
// p.s. not sure this is exactly the right syntax without compiling it.
tracker.Add((ResultType (Quad::*)(Multi&) &Quad::track);
But then you have an actual pointer that cannot subsequently be used as a template parameter.
The only thing I think you could do is to use a macro, though it is arguable if it really improves syntax here. I'd say it probably adds an unnecessary level of obfuscation.
e.g.
#define TMFN_ARGS(C, M, P1) C, P1, &C::M
tracker.Add<TMFN_ARGS(Quad, track, Multi)>();
EDIT:
However, if the name of the function is Always 'track', you could do something along the following lines:
template <typename C, typename P1>
void AddTrack() {
Add<C, P1, &C::track>();
}
tracker.AddTrack<Quad, Multi>();
I'm new to C++, and unfortunately I cannot stop thinking in C# (my former language).
I read some books, forums and the C++ reference website, but I couldn't find an answer to my question, so I thought I might as well try here before giving up and writing something ugly.
Ok, we can start.
I have a class with an abstract method succesorsFunction and I would like it to return a collection of pointers to State. I don't want to force the implementors to a specific container; I rather let them choose (vector, list, etc).
So it looks like this:
class Problem
{
public:
virtual list<const State*>::iterator succesorsFunction(const State &state, list<const State*>::iterator result) const = 0;
};
the problem here is the explicit use of list. How do you do it in C++?
I thought about using templates, but then I encountered two problems:
1) It seems like you cannot do it with abstract methods (or am I wrong?)
2) How do I tell the template it should contain pointers to State?
You can't overload methods based on return types in C++.
Also, "containers" in C++ don't have the same base (like Collection in Java), so you can't return a generic container.
I'm afraid there's no clean way of doing this.
I would just write overloads (by parameter) or different function names.
For your questions:
1) You can. What makes you think you can't?
2) The same way you declared list: list<const State*> - const is optional.
If you really want to enforce STL container usage, try the following:
template <template <typename,
typename = std::allocator<const State *> > class Container>
Container<const State*> successorsFunction(const State &state, const Container<const State*> &c) const
{
// return something useful.
}
If you insist on having this function be virtual, then it can't be a member function template, just overload it with the types you intend to support, then you can make them virtual.
You can't have a member function template which is virtual, but you can try implement friend generic function like this:
template <typename yourType>
yourType& succesorsFunction(const State &a, yourType &result){//Your return type can be without reference
//Your body
return result;
}
If you call your function for example with vector<State> a argument like this:
sucessorsFunction(b,a);// b is your State object
deduction process will automatically conclude that yourType is actually vector<State> type, which I think resolves your problem. Also, this arhitecture aloves you to create for example new class type MyVector (which holds arrays of States) and pass MyVector object to succesorsFunction.
This is just an elaboration to C.T's answer. Please remember that if you return a container of pointers then you will have to release them explicitly or use std::unique_ptr .
Just a FYI.. as you are from C# background.
You could use State or templatize it as well.
template<typename Type,
template< typename, typename = std::allocator<Type*> > class Container
>
Container<Type*> Successor(const Type& x)
{
Container<Type*> cont;
// something.
cont.push_back(new Type(x));
return cont;
}
and call it
vector<State*> states = Successor<State, vector>(State(10));
Could you have:
template <class T>
const T &operator[] (unsigned int x)
My thinking was if you have a map<string,string> it would be nice to have a wrapper class which lets you do:
obj["IntVal"]="12";
obj["StringVal"]="Test";
int i = obj["IntVal"];
How close to this can we actually get in C++? Is it worth the pain?
You can also do
class Class {
struct Proxy {
template<typename T> T as() { ... }
template<typename T> operator T() { return as<T>(); }
private:
Proxy(...) { ... }
Proxy(Proxy const&); // noncopyable
Proxy &operator=(Proxy const&);
friend class Class;
};
public:
Proxy operator[](std::string const& s) { ... }
};
Class a;
int i = a["foo"];
int i = a["foo"].as<int>();
T will be deduced to whatever the to be initialized object is. And you are not allowed to copy the proxy. That said, i prefer an explicit as<T> function like another one proposed too.
You can't - in:
int i = obj["IntVal"];
the actual type of T can't be inferred from the context since the return type isn't part of the function signature.
Moreover, storing integer values as strings is not considered as best practices, due to memory and performance considerations ;-)
Not worth it.
Templating the return type means you'd have to explicitly specify the template parameter when you call it. Something like this, maybe I have the syntax wrong:
int i = obj.operator[]<int>("IntVal");
C++ does not deduce template parameters from what you assign the result of the call to, only from the parameters you call the function with.
So you might as well just define a normal function:
int i = obj.get<int>("IntVal");
Or in this case, either do this or implement get using this:
int i = boost:lexical_cast<int>(obj["IntVal"]);
As Amit says, you could define operator[] to return a type which can be converted either to int or to other types. Then your example code can be made to compile without the explicit lexical_cast.
Have you looked at boost variant? Is this what you're looking for?
Well, what you wrote in your sample code doesn't match the question. Right now, you only have the return type templated.
But if you wanted to do something like:
template <class T>
const T &operator[const T& x]
that's valid, though maybe not terribly useful.
A map already provides an overloaded operator[] that does most of what you want. The thing you seem to want that's missing is implicit conversion from a string that happens to contain digits to an integer. One of the fundamental characteristics of C++ is static typing, which says that shouldn't be allowed -- so it's not. It'll be happy to do that conversion if you want, but you'll have to ask for it:
int i = lexical_cast<int>(obj["IntVal"]);
Alternatively, you could create a string-like class that supported implicit conversion to int. Personally, I'd advise against that. I don't object to implicit conversions nearly as strongly as many people do, but that still strikes me as a pretty lousy idea, at least for most general use.
I'm a little lost in how to cast templates. I have a function foo which takes a parameter of type ParamVector<double>*. I would like to pass in a ParamVector<float>*, and I can't figure out how to overload the casting operator for my ParamVector class, and Google isn't helping me that much. Does anyone have an example of how to do this? Thanks.
EDIT: Adding some code, sorry I'm an idiot and didn't phrase the original question well at all;
template<class T> class ParamVector
{
public:
vector <T> gnome;
vector <T> data_params;
}
template<class T> class ParamVectorConsumer
{
public:
ParamVector<T> test;
}
ParamVector<float> tester;
ParamVectorConsumer<double> cons;
cons.ParamVector = tester
will fail to compile. I would like to know how to write it so that I can cast the float version of tester to a ParamVector double. Thanks
EDIT2: Casting was the wrong word. I don't mind writing extra code, I just need to know how to get this to be accepted by the compiler so that I can write some sort of conversion code.
I'm not sure but maybe you need some like this:
template< typename TypeT >
struct ParamVector
{
template < typename NewTypeT >
operator ParamVector< NewTypeT >()
{
ParamVector< NewTypeT > result;
// do some converion things
return result;
}
template< typename NewTypeT >
ParamVector( const ParamVector< NewTypeT > &rhs )
{
// convert
}
template < typename NewTypeT >
ParamVector& operator=( const ParamVector< NewTypeT > &rhs )
{
// do some conversion thigns
return *this;
}
};
ParamVector< double > d1;
ParamVector< float > f1;
f1 = d1;
You can choose use conversion operator or operator= - I've provided both in my example.
Well, you can't. Each different actual template parameter, makes an entirely new class, which has no* relation inheritance relation with any any other class, with a diffent actual argument, made from that template.
No relationship. Well, except that each provides the same interface, so that inside a template you can handle then the same.
But neither the static types or the dynamic types have any relation.
Let me drop back here, and explain.
When I declare a pointer to classtype, like
Foo fp*;
fp has what we call a static type, of pointer-to Foo. If class Bar is a subclass of Foo, and I point fp at new Bar:
fp = new Bar1();
then we say that the object pointed to by fp has the dynamic type of Bar.
if Bar2 also publicly derives from Foo, I can do this:
fp = new Bar2();
and without ever even knowing what fp points to, I can call virtual methods declared in Foo, and have the compiler make sure that the method defined in he dynamic type pointed to is what's called.
For a template< typename T > struct Baz { void doSomething(); };
Baz<int> and Baz<float> are two entirely different class types, with no relationship.
The only "relationship" is that I can call doSomething() on both, but since the static types have no relationship, if I have a Baz<int> bi*, I can't point it to a Baz<float>. Not even with a cast. The compiler has no way to "translate" a call to the Baz doSotheing method into a call to a Baz::doSomething() method. That's because there is no "Baz method", there is no Baz, there are ony Baz<int>s and Baz<float>s, and Baz<whatevers>, but there's no common parent. Baz is not a class, Baz is a template, a set of instructions about how to make a class if and only if we have a T parameter that's bound to an actual type (or to a constant).
Now there is one way I can treat those Bazes alike: in a template, they present the same interface, and the compiler, if it knows what kind of Baz we're really dealing with, can make a static call to that method (or a static access of a member variable).
But a template is not code, a template is meta-code, the instructions of how to synthesize a class. A "call" in a template is not a call,it's an instruction of how to write the code to make a call.
So. That was long winded and confusing. Outside of a template definition, there is no relationship between a ParamVector and aParamVector. So your assignment can't work.
Well. Almost.
Actually, with partial application of templates, you can write a template function which gives a "recipe" of how to transform a Paramvector<T> to a ParamVector<U>. Notice the T and the U. If you can write code to turn any kind of ParamVector, regardless of actual template parameter into any other kind of ParamVector, you can package that up as a partially applied template, and the compiler will add that function to, for example, ParamVector.
That probably involves making a ParamVector<U>, and transforming each T in the ParamVector<T> into a U to put in the ParamVector<U>. Which still won't let you asign to a ParamConsumer<T>.
So maybe you want to have both templates and inheritance. In that case, you can same that all ParamVectors regardless of type inherit from some non-template class. And then there would be a relationship between ParamVectors, they'd all be sibling subclasses of that base class.
Notice that when you do an implicit cast, what the compiler can do without your help (I mean, without additional code) is just reference-upcast. That means that, seeing the object as a reference (for cast purposes only, the nature of the object doesn't change of course), it can look at it as one of its ancestors. When you have two template instances, none of them is an ancestor of the other (neither they are necessarily in the same hierarchy).
After trying that, the compiler looks for cast operators, constructors, etc. At this stage, probably a temporary object needs to be created, except when you're doing attribution and there's an attribution operator that fits.
One solution to your problem would be to use a conversion constructor:
template<class T> class ParamVector
{
public:
vector <T> gnome;
vector <T> data_params;
ParamVector()
{
}
template <class T2> ParamVector(const ParamVector<T2> &source)
{
gnome.reserve(source.gnome.size());
copy(source.gnome.begin(), source.gnome.end(), gnome.begin());
data_params.reserve(source.data_params.size());
copy(source.data_params.begin(), source.data_params.end(), data_params.begin());
}
};
This would create a temporary object whenever you use an instance of the template and other is required. Not a good solution if you're dealing with large containers, the overhead isn't acceptable. Also, if you pass a template instance to a function that requires not an object but a reference, the compiler won't call the conversion constructor automatically (you have to do an explicit call).
You are lost because you can't do it - the two types are completely different. Whenever you come across the need for a cast in your code, you should examine both your code and your design very closely - one or both is probably wrong.
You can't do this with a direct cast because double and float are completly different sizes. Doubles are going to be 64 bits while floats are 32. A pointer forced to cast from a
ParamVector<float>
to
ParamVector<double>
is going to misinterpret the data and give you garbage. You may want to google "pointer aliasing" or just learn more about pointers in general to see how this isn't going to work.
Think about it for a second you have one array that is a bunch of 64 bit values with fields layed out like this
0 => abcdabcd12341234
1 => abcdabcd12341234
If you force this to be interpreted as an array of 32 bit values, its going to not be interpreted correctly. You may or may not get something like
0 => abcdabcd
1 => 12341234
2 => abcdabcd
3 => abcdabcd
or it could be switched so that the 12341234's come first, or something stranger due to how the word ordering works out.
You mentioned "template casting" in your headline, so I'll presume that ParamVector is a templated type. That means that foo could be templated as well, and that would solve your problem.
template <typename T>
void foo(ParamVector<T> const& data)
{
}
You can't cast templates like this because the types are unrelated.
However, you can add a conversion function, such as:
(Your code wasn't really complete, so I can post complete code either. Hopefully you will get the idea.)
template<class T> class ParamVectorConsumer
{
public:
ParamVector<T> test;
template<T2> ParamVectorConsumer<T2> convert()
{
ParamVectorConsumer<T2> ret;
ret = this->...
}