I'm having a really hard time finding information about these kind of stuff! :(
I'm confused why this isn't working:
vector<B*> b;
vector<C*> c;
(B and C are subclasses of A)
(both are also initialized and contain elements etc etc...)
template <class First, class Second>
bool func(vector<First*>* vector1, vector<Second*>* vector2)
return vector1 == vector2;
When compiling this returns:
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
I don't see why this wouldn't work, pointers hold addresses yeah? So why don't it just compare if the two vector pointers... point to the same address(-es)?
Here's a simple example where what you're asking for won't work.
struct A{ int i; };
struct OhNoes { double d; };
struct B: public A {};
struct C: public OhNoes, public B {};
So here, B and C are both subclasses of A.
However, an instance of C is unlikely to have the same address as its B subobject.
That is, this:
C c;
B *b = &c; // valid upcast
assert(static_cast<void*>(b) == static_cast<void *>(&c));
will fail.
Your two vectors are different types and you cannot compare them.
If you want to check that you do not call func(b, b) then you can try:
template <typename T> bool func(vector<T> const & a, vector<T> const & b)
{
if (&a == &b) return false;
// do stuff
return true;
}
Unless you are doing something very strange then the pointers to two vectors of a different types will not be equal. If you try and call func with two vectors of a different type then you will get a compiler error.
Related
I have a template class which has a lot of variables, all of the same type
template<typename T>
struct Location
{
T lat;
T lon;
T alt;
// and roughly 20 variables more of type T
};
In my code T is either float or double, depending on the precision I need. Sometimes I need to cast between these two struct. Thus I want to define a conversion operator
template<typename A, typename B> operator Location<B> {
Location<B> ret;
// cast every variable in *this from type A to type B
return ret;
}
Since there are a lot of variables in Location and it is very likely that I will need to add more variables to the struct in future, I do not want to write each cast by hand in my conversion operator.
Thus, I want to know whether there is some automagically way to cast all variables in the struct?
I'm afraid there's not such a way. I would probably write templated copy constructor and assign each variable manually. You'll do it just once now, and then everytime you add a new variable - it's not a big deal IMO.
You cannot do that natively.
one function that you can write, which might be useful in another contexts (such as comparison) is a tie/as_tuple method:
template<typename T>
struct Location
{
T lat;
T lon;
T alt;
// and roughly 20 variables more of type T
auto as_tuple() const { return std::tie(lat, lon, alt /*, ..*/); }
template <typename T2> operator Location<T2>() const
{
return std::make_from_tuple<Location<T2>>(as_tuple());
// return std::apply([](auto... args){ return Location<T2>{static_cast<T2>(args)...}; },
// as_tuple());
}
};
Personally i never had this usecase, but if all entries in that struct are of the same type shouldn't something like the following work?
template<typename T>
struct Location {
T a;
T b;
T c;
template<typename B> operator Location<B>() {
if constexpr(std::is_same_v<T,B>) {
return *this;
}
Location<B> ret;
constexpr std::size_t count = sizeof(Location<T>)/sizeof(T);
static_assert(sizeof(Location<B>)==sizeof(B)*count);
for (std::size_t i=0;i<count;++i){
B b;
T a;
memcpy(&a, ((char*)this)+i*sizeof(T), sizeof(T));
b = static_cast<B>(a);
memcpy(((char*)&ret) + i*sizeof(B), &b, sizeof(B));
}
return ret;
}
};
I'm quite sure that somewhere in that monstrosity is UB or at least issues with memory alignment.
This obviously won't work with pointers or types/structs which contain pointers.
There is no good way to do this... but here is a completely terrible way that should never be used and works only if Location contains only T instances. There may also be alignment issues.
template<typename B>
operator Location<B>() const {
Location<B> ret;
for (int i = 0; i <= (sizeof(Location<T>) / sizeof(T)); i++) {
*(&ret.lat + i) = B(*(&lat + i));
}
return ret;
}
I overloaded the operator+ for a self written class further I deal with instances of these class via smart pointers. Now I am wondering if there isn't a better way to make use of the operator. Further I do not get how to pack them back into a shared_ptr.
class A
{
A operator + (A const & other)
{ //do some addition stuff and return new A}
};
std::shared_ptr<A> a, b;
//Currently I add them up like this
auto c = *a.get() + *b.get()
The dereference operator is overloaded for the "smart pointers".
You should add them up like this:
*a + *b
If you want a shared object with the result, you make a shared object from it:
auto c = std::make_shared<A>(*a + *b);
If you had raw pointers you would do this:
auto c = new A(*a + *b);
The similarity is not a coincidence.
On a side note, unless you really intend to share an object among multiple owners, you should not be using shared_ptr at all.
Is there a better way to add two smart pointers?
You cannot add smart pointers. What you're doing here is indirecting through smart pointers and adding the pointed objects.
The call to get() is redundant. You can indirect through the smart pointer directly: *a + *b.
Further I do not get how to pack them back into a shared_ptr
A simple way to create a shared pointer is std::make_shared.
You can implement an operator for a shared_ptr specialization:
class A
{
...
};
std::shared_ptr<A> operator+(const std::shared_ptr<A>& a1, const std::shared_ptr<A>& a2)
{
return std::make_shared<A>(*a1 + *a2);
}
and simple use
std::shared_ptr<A> a1, a2;
std::shared_ptr<A> a3 = a1 + a2;
A full example could be
class Value
{
private:
int value;
public:
Value(int value_): value(value_)
{}
Value operator+(Value other) const
{
return Value(value + other.value);
}
};
std::shared_ptr<Value> operator+(const std::shared_ptr<Value>& a, const std::shared_ptr<Value>& b)
{
return std::make_shared<Value>(*a + *b);
}
So you could use
Value a, b;
Value c = a + b;
and also
std::shared_ptr<Value> pa, pb;
std::shared_ptr<Value> pc = pa + pb;
The current implementation for general swap in the standard library is something like
template <class T>
void swap(T& a, T& b) {
T c(move(a));
a = move(b);
b = move(c);
}
I'm wondering whether I can do the following instead.
template <class T>
void swap(T& a, T& b) {
unsigned char x;
auto pa = reintepret_cast<unsigned char*>(&a);
auto pb = reintepret_cast<unsigned char*>(&b);
auto pc = pa + sizeof(a);
while (pa != pc) {
x = *pa;
*pa = *pb;
*pb = x;
++pa, ++pb;
}
}
I think this implementation is better in terms of space usage, as it takes only one byte.
There are many considerations that need to be addressed when swapping classes. For POD types, swapping bytes works correctly. More complicated classes, however, may rely on invariants that byte-swapping won't respect. For example, consider a reference to a member variable:
struct Foo {
Foo() : bar{}, barRef{bar} {};
int bar;
int& barRef; // Expected to refer to the neighboring `bar`
};
int main()
{
Foo f{};
{
Foo g{};
byte_swap(f, g);
}
// `f` is now invalid: `f.barRef` is pointing to garbage
}
You have to consider that every class can define what should happen when an instance is copied or moved by it's own. Sometimes a class may do something different then just move it's bytes. Maybe the class stores a pointer which is pointing to a member of the same instance. Just copying the bytes would breake the instace then.
I also thing that it will not make much difference. It is not really noticeable when the application needs 60 bytes more.
struct classcomp ;
typedef struct basic{
int a ;
set<base*,classcomp> b ;
int c ;
} base ;
classcomp{
bool operator() (const base& *lhs, const base& *rhs) const{
return (*lhs).a < (*rhs).a;}
};
I want to create a set of pointers of datatype base with comparator function classcomp .where does my code gone wrong.Someone please help
From all I see in your code, you've several places where you're trying to use dependent declarations that don't exist yet. Fixing the various problems, one way to do this is:
struct base; //forward decl announces this will exist (sooner or later)
struct classcomp
{
// uses forward decl from before in arguments. since we're
// using pointers, no other type info is required. we don't
// actually implement this yet (we can't, we don't know what
// "base" really is yet).
bool operator ()(const base* lhs, const base* rhs) const;
};
// now we define "base". when the set is declared we provide it a
// custom comparator type that has yet to be fully fleshed out, but
// that's ok. we know what it *will* look like (it provides the
// proper operator() overload).
struct base
{
int a;
std::set<base*, classcomp> b ;
int c;
};
// now we know what a "base" looks like. we can use that to
// implement the comparator operator () and finish what we
// started from before.
inline bool classcomp::operator()(const base* lhs, const base* rhs) const
{
return lhs->a < rhs->a;
}
From there, you can use base as-is or derive from it and shove shove pointers of either into the b collection of a given base (which I wouldn't do, as I would have foisted all of this using smart pointers, but that's another issue separate from this question).
Nested Comparator
This can get considerably simpler if you nest the comparator within base in the first place, and you may want to consider that. In doing so it bring everything you need in one place:
struct base
{
struct cmp_ptr
{
bool operator()(const base* lhs, const base* rhs) const
{
return lhs->a < rhs->a;
}
};
int a;
std::set<base*, cmp_ptr> b ;
int c;
};
Personally, I prefer the latter. If you need to use the comparator type somewhere else, it can be acquired using base::cmp_ptr, which is much clearer (to me at least) in its intent.
Hope it helps.
classcomp {...}; should be struct classcomp{...}; and add a forward declaration of struct base or class base.
Or change the first template parameter of std::set to basic if you intend to do the same.
Also the type classcomp is not complete when you use it. Ensure that struct classcomp definition is available before class basic.
Offtopic but you can better re-write your classcomp less cryptic as:
struct classcomp {
bool operator() (const base *lhs, const base *rhs) const {
return lhs->a < rhs->a;
}
};
Define it this way
struct classcomp {
bool operator() (const base& *lhs, const base& *rhs) const {
return (*lhs).a < (*rhs).a;
}
};
struct base {
int a;
set<base *, classcomp> b;
int c;
};
I have a struct that's defined like this:
struct Vec3 {
float x, y, z;
}
When I attempted to use std::unique on a std::vector<Vec3>, I was met with this error:
Description Resource Path Location Type
no match for ‘operator==’ in ‘_first._gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* with _Iterator = Vec3*, _Container = std::vector > == _next._gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* with _Iterator = Vec3*, _Container = std::vector >’ ModelConverter line 4351, external location: /usr/include/c++/4.4.6/bits/stl_algo.h C/C++ Problem
I understand the the necessity of the naievite of the compiler in inequality operators and others (in this case, * would almost certainly not be what I mean), but is this a matter of policy, or is there a technical reason for it that I'm not aware of? There's a default assignment operator, so why no default equality operator?
There's no technical reason. Pedantically, you might say this is because C doesn't let you compare two structures with ==, and this is a good reason; that behavior switching when you go to C++ is non-obvious. (Presumably, the reason that C doesn't support that is that field-wise comparison might work for some structs, but definitely not all.)
And just from a C++ point of view, what if you have a private field? A default == technically exposes that field (indirectly, but still). So would the compiler only generate an operator== if there are no private or protected data members?
Also, there are classes that have no reasonable definition of equality (empty classes, classes that do not model state but cache it, etc.), or for whom the default equality check might be extremely confusing (classes that wrap pointers).
And then there's inheritance. Deciding what to do for operator== in a situation of inheritance is complicated, and it'd be easy for the compiler to make the wrong decision. (For example, if this was what C++ did, we would probably be getting questions about why == always succeed when you test equality between two objects that are both descendants of an abstract base class and being used with a reference to it.)
Basically, it's a thorny problem, and it's safer for the compiler to stay out of it, even considering that you could override whatever the compiler decided.
The question of why you have to provide operator== is not the same as the question of why you have to provide some comparison function.
Regarding the latter, the reason that you are required to provide the comparison logic, is that element-wise equality is seldom appropriate. Consider, for example, a POD struct with an array of char in there. If it’s being used to hold a zero-terminated string, then two such structs can compare unequal at the binary level (due to arbitrary contents after the zero bytes in the strings) yet being logically equivalent.
In addition, there are all the C++ level complications mentioned by other answers here, e.g. the especially thorny one of polymorphic equality (you really don’t want the compiler to choose!).
So, essentially, there is simply no good default choice, so the choice is yours.
Regarding the former question, which is what you literally asked, why do you have to provide operator==?
If you define operator< and operator==, then the operator definitions in namespace std::rel_ops can fill in the rest for you. Presumably the reason why operator== is needed is that it would be needlessly inefficient to implement it in terms of operator< (then requiring two comparisons). However, the choice of these two operators as basis is thoroughly baffling, because it makes user code verbose and complicated, and in some cases much less efficient than possible!
The IMHO best basis for comparison operators is instead the three-valued compare function, such as std::string::compare.
Given a member function variant comparedTo, you can then use a Curiously Recurring Template Pattern class like the one below, to provide the full set of operators:
template< class Derived >
class ComparisionOps
{
public:
friend int compare( Derived const a, Derived const& b )
{
return a.comparedTo( b );
}
friend bool operator<( Derived const a, Derived const b )
{
return (compare( a, b ) < 0);
}
friend bool operator<=( Derived const a, Derived const b )
{
return (compare( a, b ) <= 0);
}
friend bool operator==( Derived const a, Derived const b )
{
return (compare( a, b ) == 0);
}
friend bool operator>=( Derived const a, Derived const b )
{
return (compare( a, b ) >= 0);
}
friend bool operator>( Derived const a, Derived const b )
{
return (compare( a, b ) > 0);
}
friend bool operator!=( Derived const a, Derived const b )
{
return (compare( a, b ) != 0);
}
};
where compare is an overloaded function, e.g. like this:
template< class Type >
inline bool lt( Type const& a, Type const& b )
{
return std::less<Type>()( a, b );
}
template< class Type >
inline bool eq( Type const& a, Type const& b )
{
return std::equal_to<Type>()( a, b );
}
template< class Type >
inline int compare( Type const& a, Type const b )
{
return (lt( a, b )? -1 : eq( a, b )? 0 : +1);
}
template< class Char >
inline int compare( basic_string<Char> const& a, basic_string<Char> const& b )
{
return a.compare( b );
}
template< class Char >
inline int compareCStrings( Char const a[], Char const b[] )
{
typedef char_traits<Char> Traits;
Size const aLen = Traits::length( a );
Size const bLen = Traits::length( b );
// Since there can be negative Char values, cannot rely on comparision stopping
// at zero termination (this can probably be much optimized at assembly level):
int const way = Traits::compare( a, b, min( aLen, bLen ) );
return (way == 0? compare( aLen, bLen ) : way);
}
inline int compare( char const a[], char const b[] )
{
return compareCStrings( a, b );
}
inline int compare( wchar_t const a[], wchar_t const b[] )
{
return compareCStrings( a, b );
}
Now, that’s the machinery. What does it look like to apply it to your class …
struct Vec3
{
float x, y, z;
};
?
Well it’s pretty simple:
struct Vec3
: public ComparisionOps<Vec3>
{
float x, y, z;
int comparedTo( Vec3 const& other ) const
{
if( int c = compare( x, other.x ) ) { return c; }
if( int c = compare( y, other.y ) ) { return c; }
if( int c = compare( z, other.z ) ) { return c; }
return 0; // Equal.
}
};
Disclaimer: not very tested code… :-)
C++20 adds this capability:
struct Vec3 {
float x, y, z;
auto operator<=>(const Vec3&) const = default;
bool operator==(X const&) const = default;
}
This is currently only implemented in GCC and clang trunk. Note that currently defaulting operator<=> is equivalent to also defaulting operator==, however there is an accepted proposal to remove this. The proposal suggests having defaulting operator<=> also imply (not be equivalent to as it is today) defaulting operator== as an extension.
Microsoft has documentation on this feature at https://devblogs.microsoft.com/cppblog/simplify-your-code-with-rocket-science-c20s-spaceship-operator/.
What would you like the equality operation to be? All the fields the same? It's not gonna make that decision for you.