1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qsize.h"
41#include "qdatastream.h"
42
43#include <private/qdebug_p.h>
44
45QT_BEGIN_NAMESPACE
46
47/*!
48 \class QSize
49 \inmodule QtCore
50 \ingroup painting
51
52 \brief The QSize class defines the size of a two-dimensional
53 object using integer point precision.
54
55 A size is specified by a width() and a height(). It can be set in
56 the constructor and changed using the setWidth(), setHeight(), or
57 scale() functions, or using arithmetic operators. A size can also
58 be manipulated directly by retrieving references to the width and
59 height using the rwidth() and rheight() functions. Finally, the
60 width and height can be swapped using the transpose() function.
61
62 The isValid() function determines if a size is valid (a valid size
63 has both width and height greater than or equal to zero). The isEmpty()
64 function returns \c true if either of the width and height is less
65 than, or equal to, zero, while the isNull() function returns \c true
66 only if both the width and the height is zero.
67
68 Use the expandedTo() function to retrieve a size which holds the
69 maximum height and width of \e this size and a given
70 size. Similarly, the boundedTo() function returns a size which
71 holds the minimum height and width of \e this size and a given
72 size.
73
74 QSize objects can be streamed as well as compared.
75
76 \sa QSizeF, QPoint, QRect
77*/
78
79
80/*****************************************************************************
81 QSize member functions
82 *****************************************************************************/
83
84/*!
85 \fn QSize::QSize()
86
87 Constructs a size with an invalid width and height (i.e., isValid()
88 returns \c false).
89
90 \sa isValid()
91*/
92
93/*!
94 \fn QSize::QSize(int width, int height)
95
96 Constructs a size with the given \a width and \a height.
97
98 \sa setWidth(), setHeight()
99*/
100
101/*!
102 \fn bool QSize::isNull() const
103
104 Returns \c true if both the width and height is 0; otherwise returns
105 false.
106
107 \sa isValid(), isEmpty()
108*/
109
110/*!
111 \fn bool QSize::isEmpty() const
112
113 Returns \c true if either of the width and height is less than or
114 equal to 0; otherwise returns \c false.
115
116 \sa isNull(), isValid()
117*/
118
119/*!
120 \fn bool QSize::isValid() const
121
122 Returns \c true if both the width and height is equal to or greater
123 than 0; otherwise returns \c false.
124
125 \sa isNull(), isEmpty()
126*/
127
128/*!
129 \fn int QSize::width() const
130
131 Returns the width.
132
133 \sa height(), setWidth()
134*/
135
136/*!
137 \fn int QSize::height() const
138
139 Returns the height.
140
141 \sa width(), setHeight()
142*/
143
144/*!
145 \fn void QSize::setWidth(int width)
146
147 Sets the width to the given \a width.
148
149 \sa rwidth(), width(), setHeight()
150*/
151
152/*!
153 \fn void QSize::setHeight(int height)
154
155 Sets the height to the given \a height.
156
157 \sa rheight(), height(), setWidth()
158*/
159
160/*!
161 Swaps the width and height values.
162
163 \sa setWidth(), setHeight(), transposed()
164*/
165
166void QSize::transpose() noexcept
167{
168 qSwap(value1&: wd, value2&: ht);
169}
170
171/*!
172 \fn QSize QSize::transposed() const
173 \since 5.0
174
175 Returns a QSize with width and height swapped.
176
177 \sa transpose()
178*/
179
180/*!
181 \fn void QSize::scale(int width, int height, Qt::AspectRatioMode mode)
182
183 Scales the size to a rectangle with the given \a width and \a
184 height, according to the specified \a mode:
185
186 \list
187 \li If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height).
188 \li If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle
189 as large as possible inside (\a width, \a height), preserving the aspect ratio.
190 \li If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle
191 as small as possible outside (\a width, \a height), preserving the aspect ratio.
192 \endlist
193
194 Example:
195 \snippet code/src_corelib_tools_qsize.cpp 0
196
197 \sa setWidth(), setHeight(), scaled()
198*/
199
200/*!
201 \fn void QSize::scale(const QSize &size, Qt::AspectRatioMode mode)
202 \overload
203
204 Scales the size to a rectangle with the given \a size, according to
205 the specified \a mode.
206*/
207
208/*!
209 \fn QSize QSize::scaled(int width, int height, Qt::AspectRatioMode mode) const
210 \since 5.0
211
212 Return a size scaled to a rectangle with the given \a width and \a
213 height, according to the specified \a mode.
214
215 \sa scale()
216*/
217
218/*!
219 \overload
220 \since 5.0
221
222 Return a size scaled to a rectangle with the given size \a s,
223 according to the specified \a mode.
224*/
225QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
226{
227 if (mode == Qt::IgnoreAspectRatio || wd == 0 || ht == 0) {
228 return s;
229 } else {
230 bool useHeight;
231 qint64 rw = qint64(s.ht) * qint64(wd) / qint64(ht);
232
233 if (mode == Qt::KeepAspectRatio) {
234 useHeight = (rw <= s.wd);
235 } else { // mode == Qt::KeepAspectRatioByExpanding
236 useHeight = (rw >= s.wd);
237 }
238
239 if (useHeight) {
240 return QSize(rw, s.ht);
241 } else {
242 return QSize(s.wd,
243 qint32(qint64(s.wd) * qint64(ht) / qint64(wd)));
244 }
245 }
246}
247
248/*!
249 \fn int &QSize::rwidth()
250
251 Returns a reference to the width.
252
253 Using a reference makes it possible to manipulate the width
254 directly. For example:
255
256 \snippet code/src_corelib_tools_qsize.cpp 1
257
258 \sa rheight(), setWidth()
259*/
260
261/*!
262 \fn int &QSize::rheight()
263
264 Returns a reference to the height.
265
266 Using a reference makes it possible to manipulate the height
267 directly. For example:
268
269 \snippet code/src_corelib_tools_qsize.cpp 2
270
271 \sa rwidth(), setHeight()
272*/
273
274/*!
275 \fn QSize &QSize::operator+=(const QSize &size)
276
277 Adds the given \a size to \e this size, and returns a reference to
278 this size. For example:
279
280 \snippet code/src_corelib_tools_qsize.cpp 3
281*/
282
283/*!
284 \fn QSize &QSize::operator-=(const QSize &size)
285
286 Subtracts the given \a size from \e this size, and returns a
287 reference to this size. For example:
288
289 \snippet code/src_corelib_tools_qsize.cpp 4
290*/
291
292/*!
293 \fn QSize &QSize::operator*=(qreal factor)
294 \overload
295
296 Multiplies both the width and height by the given \a factor, and
297 returns a reference to the size.
298
299 Note that the result is rounded to the nearest integer.
300
301 \sa scale()
302*/
303
304/*!
305 \fn bool operator==(const QSize &s1, const QSize &s2)
306 \relates QSize
307
308 Returns \c true if \a s1 and \a s2 are equal; otherwise returns \c false.
309*/
310
311/*!
312 \fn bool operator!=(const QSize &s1, const QSize &s2)
313 \relates QSize
314
315 Returns \c true if \a s1 and \a s2 are different; otherwise returns \c false.
316*/
317
318/*!
319 \fn const QSize operator+(const QSize &s1, const QSize &s2)
320 \relates QSize
321
322 Returns the sum of \a s1 and \a s2; each component is added separately.
323*/
324
325/*!
326 \fn const QSize operator-(const QSize &s1, const QSize &s2)
327 \relates QSize
328
329 Returns \a s2 subtracted from \a s1; each component is subtracted
330 separately.
331*/
332
333/*!
334 \fn const QSize operator*(const QSize &size, qreal factor)
335 \relates QSize
336
337 Multiplies the given \a size by the given \a factor, and returns
338 the result rounded to the nearest integer.
339
340 \sa QSize::scale()
341*/
342
343/*!
344 \fn const QSize operator*(qreal factor, const QSize &size)
345 \overload
346 \relates QSize
347
348 Multiplies the given \a size by the given \a factor, and returns
349 the result rounded to the nearest integer.
350*/
351
352/*!
353 \fn QSize &QSize::operator/=(qreal divisor)
354 \overload
355
356 Divides both the width and height by the given \a divisor, and
357 returns a reference to the size.
358
359 Note that the result is rounded to the nearest integer.
360
361 \sa QSize::scale()
362*/
363
364/*!
365 \fn const QSize operator/(const QSize &size, qreal divisor)
366 \relates QSize
367 \overload
368
369 Divides the given \a size by the given \a divisor, and returns the
370 result rounded to the nearest integer.
371
372 \sa QSize::scale()
373*/
374
375/*!
376 \fn QSize QSize::expandedTo(const QSize & otherSize) const
377
378 Returns a size holding the maximum width and height of this size
379 and the given \a otherSize.
380
381 \sa boundedTo(), scale()
382*/
383
384/*!
385 \fn QSize QSize::boundedTo(const QSize & otherSize) const
386
387 Returns a size holding the minimum width and height of this size
388 and the given \a otherSize.
389
390 \sa expandedTo(), scale()
391*/
392
393/*!
394 \fn QSize QSize::grownBy(QMargins margins) const
395 \fn QSizeF QSizeF::grownBy(QMarginsF margins) const
396 \since 5.14
397
398 Returns the size that results from growing this size by \a margins.
399
400 \sa shrunkBy()
401*/
402
403/*!
404 \fn QSize QSize::shrunkBy(QMargins margins) const
405 \fn QSizeF QSizeF::shrunkBy(QMarginsF margins) const
406 \since 5.14
407
408 Returns the size that results from shrinking this size by \a margins.
409
410 \sa grownBy()
411*/
412
413/*****************************************************************************
414 QSize stream functions
415 *****************************************************************************/
416#ifndef QT_NO_DATASTREAM
417/*!
418 \fn QDataStream &operator<<(QDataStream &stream, const QSize &size)
419 \relates QSize
420
421 Writes the given \a size to the given \a stream, and returns a
422 reference to the stream.
423
424 \sa {Serializing Qt Data Types}
425*/
426
427QDataStream &operator<<(QDataStream &s, const QSize &sz)
428{
429 if (s.version() == 1)
430 s << (qint16)sz.width() << (qint16)sz.height();
431 else
432 s << (qint32)sz.width() << (qint32)sz.height();
433 return s;
434}
435
436/*!
437 \fn QDataStream &operator>>(QDataStream &stream, QSize &size)
438 \relates QSize
439
440 Reads a size from the given \a stream into the given \a size, and
441 returns a reference to the stream.
442
443 \sa {Serializing Qt Data Types}
444*/
445
446QDataStream &operator>>(QDataStream &s, QSize &sz)
447{
448 if (s.version() == 1) {
449 qint16 w, h;
450 s >> w; sz.rwidth() = w;
451 s >> h; sz.rheight() = h;
452 }
453 else {
454 qint32 w, h;
455 s >> w; sz.rwidth() = w;
456 s >> h; sz.rheight() = h;
457 }
458 return s;
459}
460#endif // QT_NO_DATASTREAM
461
462#ifndef QT_NO_DEBUG_STREAM
463QDebug operator<<(QDebug dbg, const QSize &s)
464{
465 QDebugStateSaver saver(dbg);
466 dbg.nospace();
467 dbg << "QSize(";
468 QtDebugUtils::formatQSize(debug&: dbg, size: s);
469 dbg << ')';
470 return dbg;
471}
472#endif
473
474
475
476/*!
477 \class QSizeF
478 \inmodule QtCore
479 \brief The QSizeF class defines the size of a two-dimensional object
480 using floating point precision.
481
482 \ingroup painting
483
484 A size is specified by a width() and a height(). It can be set in
485 the constructor and changed using the setWidth(), setHeight(), or
486 scale() functions, or using arithmetic operators. A size can also
487 be manipulated directly by retrieving references to the width and
488 height using the rwidth() and rheight() functions. Finally, the
489 width and height can be swapped using the transpose() function.
490
491 The isValid() function determines if a size is valid. A valid size
492 has both width and height greater than or equal to zero. The
493 isEmpty() function returns \c true if either of the width and height
494 is \e less than (or equal to) zero, while the isNull() function
495 returns \c true only if both the width and the height is zero.
496
497 Use the expandedTo() function to retrieve a size which holds the
498 maximum height and width of this size and a given
499 size. Similarly, the boundedTo() function returns a size which
500 holds the minimum height and width of this size and a given size.
501
502 The QSizeF class also provides the toSize() function returning a
503 QSize copy of this size, constructed by rounding the width and
504 height to the nearest integers.
505
506 QSizeF objects can be streamed as well as compared.
507
508 \sa QSize, QPointF, QRectF
509*/
510
511
512/*****************************************************************************
513 QSizeF member functions
514 *****************************************************************************/
515
516/*!
517 \fn QSizeF::QSizeF()
518
519 Constructs an invalid size.
520
521 \sa isValid()
522*/
523
524/*!
525 \fn QSizeF::QSizeF(const QSize &size)
526
527 Constructs a size with floating point accuracy from the given \a
528 size.
529
530 \sa toSize()
531*/
532
533/*!
534 \fn QSizeF::QSizeF(qreal width, qreal height)
535
536 Constructs a size with the given \a width and \a height.
537*/
538
539/*!
540 \fn bool QSizeF::isNull() const
541
542 Returns \c true if both the width and height are 0.0 (ignoring the sign);
543 otherwise returns \c false.
544
545 \sa isValid(), isEmpty()
546*/
547
548/*!
549 \fn bool QSizeF::isEmpty() const
550
551 Returns \c true if either of the width and height is less than or
552 equal to 0; otherwise returns \c false.
553
554 \sa isNull(), isValid()
555*/
556
557/*!
558 \fn bool QSizeF::isValid() const
559
560 Returns \c true if both the width and height is equal to or greater
561 than 0; otherwise returns \c false.
562
563 \sa isNull(), isEmpty()
564*/
565
566/*!
567 \fn int QSizeF::width() const
568
569 Returns the width.
570
571 \sa height(), setWidth()
572*/
573
574/*!
575 \fn int QSizeF::height() const
576
577 Returns the height.
578
579 \sa width(), setHeight()
580*/
581
582/*!
583 \fn void QSizeF::setWidth(qreal width)
584
585 Sets the width to the given \a width.
586
587 \sa width(), rwidth(), setHeight()
588*/
589
590/*!
591 \fn void QSizeF::setHeight(qreal height)
592
593 Sets the height to the given \a height.
594
595 \sa height(), rheight(), setWidth()
596*/
597
598/*!
599 \fn QSize QSizeF::toSize() const
600
601 Returns an integer based copy of this size.
602
603 Note that the coordinates in the returned size will be rounded to
604 the nearest integer.
605
606 \sa QSizeF()
607*/
608
609/*!
610 Swaps the width and height values.
611
612 \sa setWidth(), setHeight(), transposed()
613*/
614
615void QSizeF::transpose() noexcept
616{
617 qSwap(value1&: wd, value2&: ht);
618}
619
620/*!
621 \fn QSizeF QSizeF::transposed() const
622 \since 5.0
623
624 Returns the size with width and height values swapped.
625
626 \sa transpose()
627*/
628
629/*!
630 \fn void QSizeF::scale(qreal width, qreal height, Qt::AspectRatioMode mode)
631
632 Scales the size to a rectangle with the given \a width and \a
633 height, according to the specified \a mode.
634
635 \list
636 \li If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height).
637 \li If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle
638 as large as possible inside (\a width, \a height), preserving the aspect ratio.
639 \li If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle
640 as small as possible outside (\a width, \a height), preserving the aspect ratio.
641 \endlist
642
643 Example:
644 \snippet code/src_corelib_tools_qsize.cpp 5
645
646 \sa setWidth(), setHeight(), scaled()
647*/
648
649/*!
650 \fn void QSizeF::scale(const QSizeF &size, Qt::AspectRatioMode mode)
651 \overload
652
653 Scales the size to a rectangle with the given \a size, according to
654 the specified \a mode.
655*/
656
657/*!
658 \fn QSizeF QSizeF::scaled(qreal width, qreal height, Qt::AspectRatioMode mode) const
659 \since 5.0
660
661 Returns a size scaled to a rectangle with the given \a width and
662 \a height, according to the specified \a mode.
663
664 \sa scale()
665*/
666
667/*!
668 \overload
669 \since 5.0
670
671 Returns a size scaled to a rectangle with the given size \a s,
672 according to the specified \a mode.
673*/
674QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
675{
676 if (mode == Qt::IgnoreAspectRatio || qIsNull(d: wd) || qIsNull(d: ht)) {
677 return s;
678 } else {
679 bool useHeight;
680 qreal rw = s.ht * wd / ht;
681
682 if (mode == Qt::KeepAspectRatio) {
683 useHeight = (rw <= s.wd);
684 } else { // mode == Qt::KeepAspectRatioByExpanding
685 useHeight = (rw >= s.wd);
686 }
687
688 if (useHeight) {
689 return QSizeF(rw, s.ht);
690 } else {
691 return QSizeF(s.wd, s.wd * ht / wd);
692 }
693 }
694}
695
696/*!
697 \fn int &QSizeF::rwidth()
698
699 Returns a reference to the width.
700
701 Using a reference makes it possible to manipulate the width
702 directly. For example:
703
704 \snippet code/src_corelib_tools_qsize.cpp 6
705
706 \sa rheight(), setWidth()
707*/
708
709/*!
710 \fn int &QSizeF::rheight()
711
712 Returns a reference to the height.
713
714 Using a reference makes it possible to manipulate the height
715 directly. For example:
716
717 \snippet code/src_corelib_tools_qsize.cpp 7
718
719 \sa rwidth(), setHeight()
720*/
721
722/*!
723 \fn QSizeF &QSizeF::operator+=(const QSizeF &size)
724
725 Adds the given \a size to this size and returns a reference to
726 this size. For example:
727
728 \snippet code/src_corelib_tools_qsize.cpp 8
729*/
730
731/*!
732 \fn QSizeF &QSizeF::operator-=(const QSizeF &size)
733
734 Subtracts the given \a size from this size and returns a reference
735 to this size. For example:
736
737 \snippet code/src_corelib_tools_qsize.cpp 9
738*/
739
740/*!
741 \fn QSizeF &QSizeF::operator*=(qreal factor)
742 \overload
743
744 Multiplies both the width and height by the given \a factor and
745 returns a reference to the size.
746
747 \sa scale()
748*/
749
750/*!
751 \fn bool operator==(const QSizeF &s1, const QSizeF &s2)
752 \relates QSizeF
753
754 Returns \c true if \a s1 and \a s2 are approximately equal; otherwise
755 returns false.
756
757 \warning This function does not check for strict equality; instead,
758 it uses a fuzzy comparison to compare the sizes' extents.
759
760 \sa qFuzzyCompare
761*/
762
763/*!
764 \fn bool operator!=(const QSizeF &s1, const QSizeF &s2)
765 \relates QSizeF
766
767 Returns \c true if \a s1 and \a s2 are sufficiently different; otherwise
768 returns \c false.
769
770 \warning This function does not check for strict inequality; instead,
771 it uses a fuzzy comparison to compare the sizes' extents.
772*/
773
774/*!
775 \fn const QSizeF operator+(const QSizeF &s1, const QSizeF &s2)
776 \relates QSizeF
777
778 Returns the sum of \a s1 and \a s2; each component is added separately.
779*/
780
781/*!
782 \fn const QSizeF operator-(const QSizeF &s1, const QSizeF &s2)
783 \relates QSizeF
784
785 Returns \a s2 subtracted from \a s1; each component is subtracted
786 separately.
787*/
788
789/*!
790 \fn const QSizeF operator*(const QSizeF &size, qreal factor)
791
792 \overload
793 \relates QSizeF
794
795 Multiplies the given \a size by the given \a factor and returns
796 the result.
797
798 \sa QSizeF::scale()
799*/
800
801/*!
802 \fn const QSizeF operator*(qreal factor, const QSizeF &size)
803
804 \overload
805 \relates QSizeF
806
807 Multiplies the given \a size by the given \a factor and returns
808 the result.
809*/
810
811/*!
812 \fn QSizeF &QSizeF::operator/=(qreal divisor)
813
814 \overload
815
816 Divides both the width and height by the given \a divisor and
817 returns a reference to the size.
818
819 \sa scale()
820*/
821
822/*!
823 \fn const QSizeF operator/(const QSizeF &size, qreal divisor)
824
825 \relates QSizeF
826 \overload
827
828 Divides the given \a size by the given \a divisor and returns the
829 result.
830
831 \sa QSizeF::scale()
832*/
833
834/*!
835 \fn QSizeF QSizeF::expandedTo(const QSizeF & otherSize) const
836
837 Returns a size holding the maximum width and height of this size
838 and the given \a otherSize.
839
840 \sa boundedTo(), scale()
841*/
842
843/*!
844 \fn QSizeF QSizeF::boundedTo(const QSizeF & otherSize) const
845
846 Returns a size holding the minimum width and height of this size
847 and the given \a otherSize.
848
849 \sa expandedTo(), scale()
850*/
851
852
853
854/*****************************************************************************
855 QSizeF stream functions
856 *****************************************************************************/
857#ifndef QT_NO_DATASTREAM
858/*!
859 \fn QDataStream &operator<<(QDataStream &stream, const QSizeF &size)
860 \relates QSizeF
861
862 Writes the given \a size to the given \a stream and returns a
863 reference to the stream.
864
865 \sa {Serializing Qt Data Types}
866*/
867
868QDataStream &operator<<(QDataStream &s, const QSizeF &sz)
869{
870 s << double(sz.width()) << double(sz.height());
871 return s;
872}
873
874/*!
875 \fn QDataStream &operator>>(QDataStream &stream, QSizeF &size)
876 \relates QSizeF
877
878 Reads a size from the given \a stream into the given \a size and
879 returns a reference to the stream.
880
881 \sa {Serializing Qt Data Types}
882*/
883
884QDataStream &operator>>(QDataStream &s, QSizeF &sz)
885{
886 double w, h;
887 s >> w;
888 s >> h;
889 sz.setWidth(qreal(w));
890 sz.setHeight(qreal(h));
891 return s;
892}
893#endif // QT_NO_DATASTREAM
894
895#ifndef QT_NO_DEBUG_STREAM
896QDebug operator<<(QDebug dbg, const QSizeF &s)
897{
898 QDebugStateSaver saver(dbg);
899 dbg.nospace();
900 dbg << "QSizeF(";
901 QtDebugUtils::formatQSize(debug&: dbg, size: s);
902 dbg << ')';
903 return dbg;
904}
905#endif
906
907QT_END_NAMESPACE
908

source code of qtbase/src/corelib/tools/qsize.cpp