I have a template class C. I want such a template copy constructor that it will resize the data array according to the size of the other class.
The following is a simple example. It works fine. However, notice that Constructor 2 and Constructor 3 are so similar, I am wondering whether it is possible to merge them as one?
Also, if I simple remove Constructor 3, then C<int> c3( c1 ) won't call Constructor 2, but will rather call a default copy constructor added by the compiler. This will result in the memory not being allocated properly.
template<typename T>
class C
{
public:
T* val;
int size;
public:
C( int s = 0 ) {
cout << "Constructor 1" << endl;
size = s;
val = ( size ) ? new T[size] : nullptr;
}
template<class T2>
C( const C<T2>& c2 ) {
cout << "Constructor 2" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
C( const C<T>& c2 ) {
cout << "Constructor 3" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
~C() {
cout << "~C()" << endl;
delete[] val;
val = nullptr;
}
};
int main(void)
{
C<int> c1( 5 );
C<float> c2( c1 );
C<int> c3( c1 );
return 0;
}
Output of the above function:
Constructor 1
Constructor 2
Constructor 3
~C()
~C()
~C()
Replace
template<class T2>
C( const C<T2>& c2 ) {
cout << "Constructor 2" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
C( const C<T>& c2 ) {
cout << "Constructor 3" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
by
template<class T2>
C( const C<T2>& c2, int dummy) {
cout << "Constructor 2" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
template<class T2>
C( const C<T2>& c2 ) : C(c2, 0) {}
C( const C<T>& c2 ) : C(c2, 0) {}
Update
You can just use:
C( int s = 0 ) {
cout << "Constructor 1" << endl;
size = s;
val = ( size ) ? new T[size] : nullptr;
}
template<class T2>
C( const C<T2>& c2 ) : C(c2.size) {}
C( const C<T>& c2 ) : C(c2.size) {}
and not need the second constructor.
One would like to implement this with a C++11 delegating constructor. However due to ambiguity in if template paramaters are to the class or to the constructor, this is not possible in a straightforward manner. As a workaround one can factor out the common code into a helper function.
something like:
template<class T2>
C( const C<T2>& c2 ) {
Copy<T2>(c2);
}
C( const C<T>& c2 ) {
Copy<T>(c2);
}
private:
template<class T2>
void Copy( const C<T2>& c2 ) {
cout << "Constructor 2" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
Related
Is there any safe std::any_cast and dynamic_cast combination?
I'm trying to perform the following:
struct V
{
virtual void x( ) { std::cout << "V"; }
};
struct A: V
{
void x( ) override { std::cout << "A"; }
};
struct B: V
{
void x( ) override { std::cout << "B"; }
};
struct C: A, B
{
void x( ) override { std::cout << "C"; }
};
int main( )
{
// In my code, I cannot change the template argument
// to be a base class and construct it with a child
// class due to requirements of my implementation
auto c = std::make_any< C >( );
#if 0 // doesn't work
std::any_cast< B >( c ).x( );
std::any_cast< A >( c ).x( );
#else // works, but requires knowing the type is C
dynamic_cast< B && >( std::any_cast< C >( c ) ).x( );
dynamic_cast< A && >( std::any_cast< C >( c ) ).x( );
#endif
}
I create a 2D vector (0,0) and would like to resize it (n,m), however, my resize function must remain const
I have tried doing
void resize(int row, int col) const
{
array.resize(row, vector<int>(col));
}
but keep getting
passing ‘const std::vector<std::vector<int>, std::allocator<std::vector<int> > >’ as ‘this’ argument discards qualifiers
How can I do this?
Matrix.h
#pragma once
#include <vector>
using namespace std;
template <typename Object>
class matrix
{
public:
matrix(int rows, int cols) : array{ rows } {
for (auto& thisRow : array)
thisRow.resize(cols);
}
matrix( initializer_list<vector<Object>> lst ) : array( lst.size( ) )
{
int i = 0;
for( auto & v : lst )
array[ i++ ] = std::move( v );
}
matrix( const vector<vector<Object>> & v ) : array{ v } {}
matrix( vector<vector<Object>> && v ) : array{ std::move( v ) } {}
matrix() {}
const vector<Object> & operator[]( int row ) const
{
return array[ row ];
}
vector<Object> & operator[]( int row )
{
return array[ row ];
}
int numrows() const
{
return array.size( );
}
int numcols() const
{
return numrows( ) ? array[ 0 ].size( ) : 0;
}
void resize(int row, int col) const
{
array.resize(row, vector<int>(col));
}
private:
vector<vector<Object>> array;
};
main.cpp
matrix<int> mat = matrix<int>();
cout << "Zero-parameter matrix (rows,cols) = (" << mat.numrows() << "," << mat.numcols() << ")" << endl;
mat.resize(4, 3);
cout << "Resized matrix to 4x3" << endl;
cout << mat << endl;
mat[2][1] = 12;
cout << "Modified (2,1)" << endl;
cout << mat << endl;
When you put const on the end of the function there, you're saying the implicit this is const. That is, you're promising not to modify the state of the object this function is being called on.
But isn't the whole point of calling resize() to modify the state of the object? If I were you, I'd take the const off of there.
In other words, you have two options: either keep your promise to not change the state of the object (perhaps by returning a resized copy?), or lose the const.
I have the following two objects. Im wondering if there is a way to have Pixel as a base class of PixelBGR so that any operator (+,-,*,/, [], etc.) could be used without redefining them ?
template<class T, std::size_t N>
struct Pixel
{
T ch[N];
inline T& operator[](const int x)
{
return ch[x];
}
};
template<class T>
struct PixelBGR
{
union
{
struct
{
T b;
T g;
T r;
};
T ch[3];
};
inline T& operator[](const int x)
{
return ch[x];
}
};
EDIT: As suggested by πάντα ῥεῖ, here more details about what Im trying to do.
Im trying to have a generic class Pixel, which will be template to handle any type or size.
The usual are 1,2,3,4,8 or 16. The class with defines some operator such as +,-,*, etc.
Since most of the time, the Pixel<T,3> is a BGR pixel, I would like to define rapid access to r,g and b to avoid confusion, but still store it as BGR.
But the derived class should also provide the Operator which will be generic based on N.
EDIT2: By reading the comment of SergeyA, I forgot to say that the struct Pixel must not change size.
So I think balki answer is the best, by using member function. I was trying to make it with variables to avoid too much char ie: adding the (), but it seems to be too complicated for nothing. I still investigating CRTP, but I dont get it well, Im reading on that.
Answering the question as asked, this should give OP reuse of the operators without any undefined behavior:
#include <cstddef>
template<class T, std::size_t N>
struct Pixel
{
T ch[N];
inline T& operator[](const int x)
{
return ch[x];
}
Pixel& operator+= (const Pixel& ) { return *this;}
};
template<class T, std::size_t N>
Pixel<T, N> operator+ (const Pixel<T, N>& l, const Pixel<T, N>& r);
template<class T>
struct BgrPixel : Pixel<T, 3> {
using base = Pixel<T, 3>;
using base::base;
BgrPixel(const base& b) : base(b) { };
T& b = base::ch[0];
T& g = base::ch[1];
T& r = base::ch[2];
};
BgrPixel<int> a, b;
BgrPixel<int> c = a + b;
Alterinative would be to have b(), g() and r() as a member functions, but this would require you to access them as functions. You would also need const and non-const versions of them.
The benefits, however, would be that the size of the struct will not be increased and copy assignment would work naturally (which, in turn, could be solved by providing custom copy assignment).
The Curiously Recurring Template Pattern (CRTP) would work well in this case. In the CRTP the Derived class is used as a template argument to the Base class. Chapter 16.3 The Curiously Recurring Template Pattern (CRTP), from the C++ Templates - The Complete Guide, by David Vandevoorde and Nicolai M. Josuttis, explains things in more detail.
From the comments below, the usage of a union{struct{...}...} causes undefined behaviour (UB), but there have been some contradicting opinions upon this. As far as I'm aware, it is a gnu extension and supported by almost every compiler. glm for example uses union-structs quite very often.
As an alternative approach, you can use aliases (references) for the r,g,b variables.
#include <iostream>
template<typename T, std::size_t N, template<typename,std::size_t> class B >
struct Pixel
{
B<T,N> *crtp = static_cast<B<T,N>*>(this);
T& operator[](std::size_t x)
{
return crtp->ch[x];
}
Pixel& operator = (const Pixel &t)
{
crtp->ch[0] = t.crtp->ch[0];
crtp->ch[1] = t.crtp->ch[1];
crtp->ch[2] = t.crtp->ch[2];
return *crtp;
}
B<T,N> operator + (const B<T,N> &t)
{
B<T,N> tmp;
tmp[0] = crtp->ch[0] + t.crtp->ch[0];
tmp[1] = crtp->ch[1] + t.crtp->ch[1];
tmp[2] = crtp->ch[2] + t.crtp->ch[2];
return tmp;
}
B<T,N> operator - (const B<T,N> &t)
{
B<T,N> tmp;
tmp[0] = crtp->ch[0] - t.crtp->ch[0];
tmp[1] = crtp->ch[1] - t.crtp->ch[1];
tmp[2] = crtp->ch[2] - t.crtp->ch[2];
return tmp;
}
};
template<typename T, std::size_t N=3>
struct PixelBGR : Pixel<T, N, PixelBGR>
{
T ch[3];
T &r;
T &g;
T &b;
PixelBGR() : ch{},r(ch[0]),g(ch[1]),b(ch[2])
{}
PixelBGR& operator = (const PixelBGR &p)
{
ch[0] = p.ch[0];
ch[1] = p.ch[1];
ch[2] = p.ch[2];
return *this;
}
};
int main()
{
PixelBGR<int> p;
p.r = 25;
p.g = 14;
p.b = 58;
std::cout<< p[0] <<" , "<<p[1]<<" , "<<p[2] <<std::endl;
PixelBGR<int> q;
q = p;
std::cout<< q[0] <<" , "<<q[1]<<" , "<<q[2] <<std::endl;
PixelBGR<int> res1;
res1 = q + p;
std::cout<< res1.r <<" , "<<res1.g<<" , "<<res1.b <<std::endl;
PixelBGR<int> res2;
res2 = q - p;
std::cout<< res2.r <<" , "<<res2.g<<" , "<<res2.b <<std::endl;
}
Result:
25 , 14 , 58
25 , 14 , 58
50 , 28 , 116
0 , 0 , 0
Example using references: https://rextester.com/AZWG4319
Example using union-struct: https://rextester.com/EACC87146
First thanks to all of you for advise, and special thanks to #Constantinos Glynos, #balki and #SergeyA for the example they provide, those help me to achieve a solution that match my need.
I implemented the BGR and BGRA to show that the N works fine, now I just need to implement all the operator, and functions that I require.
Please feel free to edit, or tell me if there is something wrong with this.
Pixel.h
#include <cstdio> // std::size_t
#include <iostream> // std::cout
template<typename T, std::size_t N, template<typename, std::size_t> class B >
struct Pixel
{
T ch[N];
// ==============================================================
// Overload the accessor (so .ch[0] == direct access with [0].
T& operator[](std::size_t x){ return ch[x]; }
// ==============================================================
// Copy-assignement
Pixel& operator=( const Pixel &t )
{
for ( int i = 0; i < N; i++ )
ch[i] = t.ch[i];
return *this;
}
// ==============================================================
// Operator
B<T, N> operator+( const B<T, N> &t )
{
B<T, N> tmp;
for ( int i = 0; i < N; i++ )
tmp[i] = ch[i] + t.ch[i];
return tmp;
}
B<T, N> operator-( const B<T, N> &t )
{
B<T, N> tmp;
for ( int i = 0; i < N; i++ )
tmp[i] = ch[i] - t.ch[i];
return tmp;
}
template<typename T, std::size_t N, template<typename, std::size_t> class B >
friend std::ostream& operator<<( std::ostream& os, const Pixel &t );
};
// To print the vector
template<typename T, std::size_t N, template<typename, std::size_t> class B >
std::ostream& operator<<( std::ostream& os, const B<T, N> &t )
{
os << "Pixel: (" << t.ch[0];
for ( int i = 1; i < N; i++ )
os << ", " << t.ch[i];
os << ")";
return os;
}
template<typename T, std::size_t N = 3>
struct BGR : Pixel<T, N, BGR>
{
T& b() { return ch[0]; }
T& g() { return ch[1]; }
T& r() { return ch[2]; }
};
template<typename T, std::size_t N = 4>
struct BGRA : Pixel<T, N, BGRA>
{
T& b() { return ch[0]; }
T& g() { return ch[1]; }
T& r() { return ch[2]; }
T& a() { return ch[3]; }
};
Main.cpp
int main() {
std::cout << "Sizeof a float BGR: " << sizeof(BGR<float>) << std::endl;
std::cout << "Sizeof a float BGRA: " << sizeof(BGRA<float>) << std::endl;
BGR<int> p;
p.r() = 25;
p.g() = 14;
p.b() = 58;
std::cout << p << std::endl;
std::cout << p[0] << " , " << p[1] << " , " << p[2] << std::endl;
std::cout << p.b() << " , " << p.g() << " , " << p.r() << std::endl;
BGR<int> q;
q = p;
std::cout << q[0] << " , " << q[1] << " , " << q[2] << std::endl;
BGR<int> res1;
res1 = q + p;
std::cout << res1.r() << " , " << res1.g() << " , " << res1.b() << std::endl;
BGR<int> res2;
res2 = q - p;
std::cout << res2.r() << " , " << res2.g() << " , " << res2.b() << std::endl;
BGRA<float> a;
a.r() = 255.0f;
a.g() = 0.0f;
a.b() = 0.0f;
a.a() = 128.5f;
BGRA<float> b = a;
std::cout << a << std::endl;
return 0;
}
I am trying to compare different classes of objects in C++.
Everything works well if I remove section3. But I'd like to know how to edit the comparative operators == and != to make it work without any errors?
The error that I get is "no match for 'operator==' (operand types are 'Fruit' and 'Plant') "
Here is my code :
#include <iostream>
#include <string>
class Plant
{
public:
Plant(std::string name) : type_(name)
{ }
bool operator==(const Plant &that) const
{ return type_ == that.type_; }
bool operator!=(const Plant &that) const
{ return !operator==(that); }
void print()
{ std::cout << type_ << std::endl; }
protected:
std::string type_;
};
class Fruit: public Plant
{
public:
Fruit(std::string name, std::string taste)
: Plant(name)
, taste_(taste)
{ }
bool operator==(const Fruit& that) const
{
return ( (taste_ == that.taste_) && (Plant::operator==(that)) );
}
bool operator!=(const Fruit& that) const
{
return !operator==(that);
}
void print()
{
Plant::print();
std::cout << taste_ << std::endl;
}
private:
std::string taste_;
};
int main()
{
Plant a("Maple");
a.print();
Plant b("Maple");
if (a == b)
{
std::cout << "a and b are equal" << std::endl;
}
else
{
std::cout << "a and b are not equal" << std::endl;
}
Fruit c("Apple","sweet");
c.print();
Fruit d("Apple","sweet");
if (c == d)
{
std::cout << "c and d are equal" << std::endl;
}
else
{
std::cout << "c and d are not equal" << std::endl;
}
if (a == c)
{
std::cout << "a and c are equal" << std::endl;
}
else
{
std::cout << "a and c are not equal" << std::endl;
}
/* Section 3 */
if (c == a)
{ std::cout <<"c and a are equal\n"<< std::endl; }
else
{ std::cout <<"c and a are not equal\n"<< std::endl; }
if (a != c)
{ std::cout <<"c and a are not equal\n"<< std::endl; }
else
{ std::cout <<"c and a are equal\n"<< std::endl; }
return 0;
}
Thanks ..
You can add non-member functions,
bool operator==(Fruit const& f, Plant const& p)
{
return false;
}
bool operator!=(Fruit const& f, Plant const& p)
{
return !(f == p);
}
This will work for one sub-type of Plant. This approach is not scalable. If you create more sub-types of Plant, you'll need to use a different approach.
You have to either implement comparitor operators to compare Fruit and Plant or downcast the Fruit to a plant in the comparison:
bool operator==(const Plant& plant, const Fruit& fruit) { /* test here */ }
bool operator==(const Fruit& fruit, const Plant& plant) { return (plant == fruit); }
Or if you have pointers:
Fruit* fruit = new Fruit("apple", "sour");
Plant* plant = new Plant("maple");
if(*plant == *static_cast<Plant*>(fruit)) {}
It's bit unclear what you're trying to achieve, but apparently it involves dynamic type checking where two objects compare equal if they dynamically are of some common base type X and are equal according to some criterion specified in that base type.
Finding the common type X is in general a thorny problem, because C++ supports multiple inheritance. But if one assumes, for simplicity, single inheritance, that is, the case where each class has at most one base class, then one can let one of the objects that are involved in a comparison, walk up the base class chain and use e.g. dynamic_cast to check if the other object is of this type, e.g. like this:
#include <string>
#include <utility> // std::move
using Byte_string = std::string;
class Base
{
private:
Byte_string s_;
protected:
virtual
auto equals( Base const& other ) const
-> bool
{ return s_ == other.s_; }
public:
friend
auto operator==( Base const& a, Base const& b )
-> bool
{ return a.equals( b ); }
explicit Base( Byte_string s )
: s_( move( s ) )
{}
};
class Derived
: public Base
{
private:
Byte_string t_;
protected:
auto equals( Base const& other ) const
-> bool override
{
if( auto p_other = dynamic_cast<Derived const*>( &other ) )
{
return Base::equals( other ) and t_ == p_other->t_;
}
return Base::equals( other );
}
public:
Derived( Byte_string s, Byte_string t )
: Base( move( s ) )
, t_( move( t ) )
{}
};
class Most_derived
: public Derived
{
private:
int u_;
protected:
auto equals( Base const& other ) const
-> bool override
{
if( auto p_other = dynamic_cast<Most_derived const*>( &other ) )
{
return Derived::equals( other ) and u_ == p_other->u_;
}
return Derived::equals( other );
}
Most_derived( Byte_string s, Byte_string t, int u )
: Derived( move( s ), move( t ) )
, u_( u )
{}
};
#include <iostream>
using namespace std;
auto main() -> int
{
Base a( "Maple" );
Base b( "Maple" );
cout << "a and b are " << (a == b? "" : "not ") << "equal.\n";
Derived c( "Apple", "sweet" );
Derived d( "Apple", "sweet" );
cout << "c and d are " << (c == d? "" : "not ") << "equal.\n";
cout << "a and c are " << (a == c? "" : "not ") << "equal.\n";
cout << "c and a are " << (c == a? "" : "not ") << "equal.\n";
Base& x = d;
cout << "x and c are " << (x == c? "" : "not ") << "equal.\n";
cout << "c and x are " << (c == x? "" : "not ") << "equal.\n";
}
I have a base class and define a operator== on it. And B is a subclass of A and I forget to define operator== on B. Then A::operator== is used on comparing B and usually this gives an unexpected results. Any good method to avoid such "forget"? I add an example to clarify my question.
class A
{
public:
bool operator==(const A& rhs) const
{
return i == rhs.i;
}
int i
};
class B : public A
{
public:
int j;
}
B b1, b2;
b1.i = 1; b1.j = 2;
b2.i = 1; b1.j = 3;
bool b = (b1 == b2); // will be true
What you could try is put A in a namespace, create operator == as a template non-member also in that namespace and let ADL take care of it.
#include <iostream>
namespace stuff {
class A
{
};
class B : public A {};
template <typename T>
bool operator == (const T &lhs, const T &rhs)
{
std::cout << __PRETTY_FUNCTION__ << '\n';
return &lhs == &rhs; // <-- replace this with something real
}
}
struct C {};
int main()
{
stuff::A a, aa;
stuff::B b, bb;
C c, cc;
b == bb;
aa == a;
aa == cc; // error: no match for "operator==" stuff::A and C
b == a; // error: no match for "operator==" stuff::B and stuff::A
}
Edit: For your edited example where you want the equality check to compare each part of the class with the other respective corresponding part, DyP's suggestion can work. For example:
// same as before
// ...
class A
{
public:
bool is_equal(const A &rhs) const { return i == rhs.i; }
};
class B : public A
{
public:
bool is_equal(const B &rhs) const { return A::is_equal(rhs) && (j == rhs.j); }
};
template <typename T>
bool operator == (const T &lhs, const T &rhs)
{
std::cout << __PRETTY_FUNCTION__ << '\n';
return lhs.is_equal(rhs);
}
Now comparing this again in the using code:
// ...
b.i = 1, bb.i = 1;
b.j = 1, bb.j = 42;
cout << boolalpha << (b == bb) << '\n';
b.j = 42;
cout << (b == bb) << '\n';
a.i = 2, aa.i = 3;
cout << (aa == a) << '\n';
outputs:
bool stuff::operator==(const T&, const T&) [with T = stuff::B]
false
bool stuff::operator==(const T&, const T&) [with T = stuff::B]
true
bool stuff::operator==(const T&, const T&) [with T = stuff::A]
false
Allowing implicit conversions for greatwolf's great approach is a bit tricky:
#include <type_traits>
namespace stuff
{
template<class T, class U>
bool operator== (const T &lhs, const U &rhs)
{
using namespace std;
static_assert(is_convertible<T, U>{} || is_convertible<U, T>{},
"invalid argument type");
static_assert
(
is_same<T, U>{}
|| ( not is_base_of<T, U>{} && not is_base_of<U, T>{})
, "use explicit casts to compare derived to base class types"
);
return is_equal(lhs, rhs);
}
template<class T>
bool is_equal(T const&, T const&)
{
// force compile-time failure when instantiating
static_assert(std::is_same<T, void>{},
"no free is_equal function for these argument types available");
return false;
}
class A
{
private:
int i;
friend bool is_equal(A const& lhs, A const& rhs)
{ return lhs.i == rhs.i; }
public:
A(int p_i) : i(p_i) {}
};
class B : public A
{
int j;
public:
B(int p_i, int p_j) : A(p_i), j(p_j) {}
};
class C : public A
{
private:
int j;
friend bool is_equal(C const& lhs, C const& rhs)
{
return is_equal(static_cast<A const&>(rhs),
static_cast<A const&>(lhs))
&& lhs.j == rhs.j;
}
public:
C(int p_i, int p_j) : A(p_i), j(p_j) {}
};
}
struct D
{
operator stuff::C() const
{
return stuff::C(1, 42);
}
};
#include <iostream>
int main()
{
stuff::A a(1), aa(1);
stuff::B b(1, 42), bb(1, 42);
stuff::C c(1, 42), cc(1, 42);
D d;
// commented lines invoke compilation failures
std::cout << "a == aa: " << (a == aa) << std::endl;
//std::cout << "a == b : " << (a == b ) << std::endl;
//std::cout << "b == bb: " << (b == bb) << std::endl;
//std::cout << "a == c : " << (a == c ) << std::endl;
std::cout << "c == cc: " << (c == cc) << std::endl;
std::cout << "d == c : " << (d == c ) << std::endl;
}
Why do you have equality comparison in a class hierarchy? In many cases, this indicates a problem with the design, with classes that don't properly behave like value types, but not properly like objects from a hierarchy either.