Please help!!

In this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Ex8_10.cpp
// Using a class template
#include <iostream>
#include <utility>                          // For operator overload templates
using std::cout;
using std::endl;
using std::move;
using namespace std::rel_ops;
        
class CBox                                  // Class definition at global scope
{
  public:
    // Constructor definition
    explicit CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0): m_Height(hv)
    {
      m_Length = std::max(lv, wv);
      m_Width = std::min(lv, wv);

      // Length is now greater than or equal to width 
      if(m_Height > m_Length)
      {
        m_Height = m_Length;
        m_Length = hv;

        // m_Height is still greater than m_Width so swap them
        double temp = m_Width;
        m_Width = m_Height;
        m_Height = temp;
      }
      else if( m_Height > m_Width)
      {
        m_Height = m_Width;
        m_Width = hv;
      }
    }
        
    // Function to calculate the volume of a box
    double Volume() const
    {
      return m_Length*m_Width*m_Height;
    }
        
    // Operator function for 'less than' that
    // compares volumes of CBox objects.
    bool operator<(const CBox& aBox) const
    {
      return this->Volume() < aBox.Volume();
    }

    // 'Less than' operator function to compare a CBox object volume with a constant
    bool operator<(const double& value) const
    {
      return this->Volume() < value;
    }

    // 'Greater than' function to compare a CBox object volume with a constant
    bool operator>(const double& value) const
    {
      return this->Volume() > value;
    }
        
    // Overloaded equality operator
    bool CBox::operator==(const CBox& aBox) const
    {
      return this->Volume() == aBox.Volume();
    }

    // Function to add two CBox objects
    CBox operator+(const CBox& aBox) const
    {
      // New object has larger length & width, and sum of heights
      return CBox(m_Length > aBox.m_Length ? m_Length : aBox.m_Length,
                  m_Width > aBox.m_Width   ?  m_Width : aBox.m_Width,
                  m_Height + aBox.m_Height);
    }

    // Function to show the dimensions of a box
    void ShowBox() const
    {
      cout << m_Length << " " << m_Width  << " " << m_Height << endl;
    }
        
  private:
    double m_Length;                        // Length of a box in inches
    double m_Width;                         // Width of a box in inches
    double m_Height;                        // Height of a box in inches
};
        
// CSamples class template definition
template <class T> class CSamples
{
  public:
    // Constructors
    CSamples(const T values[], int count);
    CSamples(const T& value);
    CSamples(T&& value);
    CSamples() : m_Free(0) {}
        
    bool Add(const T& value);               // Insert a value
    bool Add(T&& value);                    // Insert a value with mve semantics
    T Max() const;                          // Calculate maximum
        
  private:
    static const size_t maxSamples = 100;   // Maximum number od sample
    T m_Values[maxSamples];                 // Array to store samples
    int m_Free;                             // Index of free location in m_Values
};

// Constructor template definition to accept an array of samples
template<class T> CSamples<T>::CSamples(const T values[], int count)
{
  m_Free = count < maxSamples ? count : maxSamples;       // Don't exceed the array
  for(int i = 0; i < m_Free; i++)
    m_Values[i] = values[i];                // Store count number of samples
}
        
// Constructor to accept a single sample
template<class T> CSamples<T>::CSamples(const T& value)
{
  m_Values[0] = value;                      // Store the sample
  m_Free = 1;                               // Next is free
}
        
// Constructor to accept a temporary sample
template<class T> CSamples<T>::CSamples(T&& value)
{
  cout << "Move constructor." << endl;
  m_Values[0] = move(value);                // Store the sample
  m_Free = 1;                               // Next is free
}
        
// Function to add a sample
template<class T> bool CSamples<T>::Add(const T& value)
{
  cout << "Add." << endl;
  bool OK = m_Free < maxSamples;                   // Indicates there is a free place
  if(OK)
    m_Values[m_Free++] = value;             // OK true, so store the value
  return OK;
}
        
template<class T> bool CSamples<T>::Add(T&& value)
{
  cout << "Add move." << endl;
  bool OK = m_Free < maxSamples;                   // Indicates there is a free place
  if(OK)
    m_Values[m_Free++] = move(value);       // OK true, so store the value
  return OK;
}
 
// Function to obtain maximum sample
template<class T> T CSamples<T>::Max() const
{
  T theMax = m_Values[0];                   // Set first sample as maximum
  for(int i = 1; i < m_Free; i++)           // Check all the samples
    if(theMax < m_Values[i])
      theMax = m_Values[i];                 // Store any larger sample
  return theMax;
}
        
int main()
{
  CBox boxes[] = {                          // Create an array of boxes
                   CBox(8.0, 5.0, 2.0),     // Initialize the boxes...
                   CBox(5.0, 4.0, 6.0),
                   CBox(4.0, 3.0, 3.0)
                 };
        
  // Create the CSamples object to hold CBox objects
  CSamples<CBox> myBoxes(boxes, _countof(boxes));
        
  CBox maxBox = myBoxes.Max();              // Get the biggest box
  cout << endl                              // and output its volume
       << "The biggest box has a volume of "
       << maxBox.Volume()
       << endl  << endl;

  CSamples<CBox> moreBoxes(CBox(8.0, 5.0, 2.0));
  moreBoxes.Add(CBox(5.0, 4.0, 6.0));
  moreBoxes.Add(CBox(4.0, 3.0, 3.0));
  cout << "The biggest box has a volume of "
       << moreBoxes.Max().Volume()
       << endl;
  return 0;
}


On line 125 and 142 there is a constructor and add operator using move semantics. There is no real advantage to the use like this right, performance wise and its just useless having two that do the exact same thing? The C++ standard says that if you use T& it will still accept rvalues as arguments.
Last edited on
Please help!
There is no real advantage to the use like this right, performance wise and its just useless having two that do the exact same thing?


Try using CSamples to contain:

1
2
3
4
5
6
7
8
9
10
11
12
class NotCopyable
{
public:
    NotCopyable() {}
    NotCopyable(NotCopyable&&) {}

    void operator=(NotCopyable&&) {}

private:
    NotCopyable(NotCopyable&) ;
    void operator=(NotCopyable&) ;
};


without them. And, of course there is an advantage for types that support move semantics. Moving is usually cheaper than copying.
But it isnt moving, its doing the exact same thing as the lvalue one?
So whats the need?
Atleast here
So whats the need?


I believe I just told you. Your container won't work for NotCopyable without the move versions but will with them, and for types that support move operations, move operations are cheaper than (or at the worst equivalent to) copy operations.

Surely you can see that generic containers are meant to work with different types, and presumably you want it to work for as many types as possible and also as efficiently as possible. If not, continue your current line of thinking.
As much as I try to understand this I just cant seem to put my finger on it. Why wont my container work for NotCopyable without the move versions?
Oh I just facepalmed so hard, I understand why there in the class, for other classes that have move semantics, and not for doubles and ints.

But why wont my container store NotCopyable?
Last edited on
I can store it in my container, I just get a warning even if the move is there or not.


This is the output

>------ Build started: Project: Tests, Configuration: Debug Win32 ------
1>  Ex8_10.cpp
1>c:\users\anmol\documents\visual studio 2012\projects\c++ book\code from book\chapter 08\ex8_10.cpp(182): warning C4930: 'CSamples<T> notcopy(NotCopyable)': prototyped function not called (was a variable definition intended?)
1>          with
1>          [
1>              T=NotCopyable
1>          ]
1>  Tests.vcxproj -> C:\Users\Anmol\documents\visual studio 2012\Projects\Tests\Debug\Tests.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========


I dont quite understand whats going. Can you please help!
Last edited on
You probably did something like:

1
2
3
4
int main()
{
    CSamples<NotCopyable> nc(NotCopyable());
}


which, as the warning says, is a function prototype. You can fix that by using an extra set of parentheses:

1
2
3
4
int main()
{
    CSamples<NotCopyable> nc((NotCopyable()));
}


or

1
2
3
4
int main()
{
    CSamples<NotCopyable> nc = NotCopyable() ;
}


Google: C++ most vexing parse
This was what I did

CSamples<NotCopyable> notcopy(NotCopyable)

But ok ill google it. But still why CSamples cant store NotCopyable, what is the reason?
Last edited on
If you remove the move versions of the member functions, it does not.

Again, CSamples<NotCopyable>notcopy(NotCopyable) is not an instance of a container holding NotCopyable objects. It is a function declaration/prototype.
Your right it doesnt? But why? o.O

Oh thanks for the vexing parse thing just learned something new :D
Please help cire!
Oh but the reason thats not copyable is cause its set to private lol.

I thought it was something more complex or something xD which is why I missed it.
It is a common thing pre-C++11 support to make a copy constructors/copy assignment operators private to disable their use. Iirc, VC++ doesn't support the delete/default specifications for constructors/assignment operators yet, so I'm not in the habit of using them.
It does VC++ does except there are no move constructors/assignment operators. Atleast I think. But thanks man!
Last edited on
Topic archived. No new replies allowed.