Everything that applies to C also applies to C++. This article contains only things that don't apply to C.
The C++ FQA has a lot of great points, so go read it too.
I believe that a programming language should be designed to make simple things simple and complex things as simple as possible. C++ is designed to make simple things complex and complex things even more complex. For example, a program to read space-separated numbers from STDIN, sort them and again output them space-separated:
import std/[strutils, sequtils, algorithm]
let nums = stdin.readLine.splitWhitespace.mapIt(it.parseInt)
echo nums.sorted.mapIt($it).join(" ")
Try it online!import Data.List
main = interact $ (++ "\n") . unwords . map show
. sort
. map (read :: String -> Int) . words
Try it online!#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> nums;
std::string inp;
while (std::getline(std::cin, inp, ' ')) {
nums.emplace_back(std::stoi(inp));
}
std::sort(nums.begin(), nums.end());
std::string sep = "";
for (int num : nums) {
std::cout << sep << num;
sep = " ";
}
std::cout << std::endl;
}
Try it online!typedef / using, #define / constexpr, char[] / std::string, int[] / std::array<int>, printf / cout, struct / classC++ took the horrible syntax of C and somehow managed to make it even worse.
struct / class definition. Just why?static, using, typename.const is used to declare immutable variables (not constants, for which there is constexpr) and it can be placed in various positions inside a type, which completely changes its meaning.:: is a good path separator?std::sort(arr.begin(), arr.end()).stoi, fscanf) to unusual words (emplace_back).std:: between everything from the standard library, which makes the code repetitive and unreadable. Who would have guessed that sort is a standard library function if it wasn't for the prefix?#include <vector>
#include <algorithm>
int main() {
int a;
std::vector<std::vector<int>> v;
std::vector<std::vector<int>>::const_iterator it = std::find(v.begin(), v.end(), a);
}Try it online!
The error message (compiled with GCC 10.2.0) has 148 lines with about 12 kB of content, starting with:
In file included from /usr/include/c++/10.2.0/bits/stl_algobase.h:71,
from /usr/include/c++/10.2.0/vector:60,
from error.cpp:1:
/usr/include/c++/10.2.0/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Iter_equals_val<lt;_Value>::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator<lt;std::vector<lt;int>*, std::vector<lt;std::vector<lt;int> > >; _Value = const int]’:
/usr/include/c++/10.2.0/bits/stl_algobase.h:1932:14: required from ‘_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<lt;std::vector<lt;int>*, std::vector<lt;std::vector<lt;int> > >; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<lt;const int>]’
/usr/include/c++/10.2.0/bits/stl_algobase.h:1977:23: required from ‘_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = __gnu_cxx::__normal_iterator<lt;std::vector<lt;int>*, std::vector<lt;std::vector<lt;int> > >; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<lt;const int>]’
/usr/include/c++/10.2.0/bits/stl_algo.h:3902:28: required from ‘_IIter std::find(_IIter, _IIter, const _Tp&) [with _IIter = __gnu_cxx::__normal_iterator<lt;std::vector<lt;int>*, std::vector<lt;std::vector<lt;int> > >; _Tp = int]’
error.cpp:7:87: required from here
/usr/include/c++/10.2.0/bits/predefined_ops.h:268:17: error: no match for ‘operator==’ (operand types are ‘std::vector<lt;int>’ and ‘const int’)
268 | { return *__it == _M_value; }
| ~~~~~~^~~~~~~~~~~
In file included from /usr/include/c++/10.2.0/bits/stl_algobase.h:67,
from /usr/include/c++/10.2.0/vector:60,
from error.cpp:1:
/usr/include/c++/10.2.0/bits/stl_iterator.h:1064:5: note: candidate: ‘template<lt;class _IteratorL, class _IteratorR, class _Container> bool __gnu_cxx::operator==(const __gnu_cxx::__normal_iterator<lt;_IteratorL, _Container>&, const __gnu_cxx::__normal_iterator<lt;_IteratorR, _Container>&)’
1064 | operator==(const __normal_iterator<lt;_IteratorL, _Container>& __lhs,
| ^~~~~~~~
/usr/include/c++/10.2.0/bits/stl_iterator.h:1064:5: note: template argument deduction/substitution failed:constexpr double pi = 3.0 // An engineer approximation
#include <iostream>
int main() {
std::cout << "Enter the radius: " << std::flush;
double radius;
std::cin >> radius;
std::cout << "Area: " << pi * radius * radius << std::endl;
}
Try it online!
The error message (compiled with GCC 10.2.0) has 3244 lines with about 250 kB of content, starting with:
In file included from /usr/include/c++/10.2.0/iostream:38,
from error.cpp:3:
/usr/include/c++/10.2.0/x86_64-pc-linux-gnu/bits/c++config.h:258:1: error: expected ‘,’ or ‘;’ before ‘namespace’
258 | namespace std
| ^~~~~~~~~
In file included from /usr/include/c++/10.2.0/iosfwd:40,
from /usr/include/c++/10.2.0/ios:38,
from /usr/include/c++/10.2.0/ostream:38,
from /usr/include/c++/10.2.0/iostream:39,
from error.cpp:3:
/usr/include/c++/10.2.0/bits/postypes.h:98:11: error: ‘ptrdiff_t’ does not name a type
98 | typedef ptrdiff_t streamsize; // Signed integral type
| ^~~~~~~~~
/usr/include/c++/10.2.0/bits/postypes.h:41:1: note: ‘ptrdiff_t’ is defined in header ‘<cstddef>’; did you forget to ‘#include <cstddef>’?
40 | #include <cwchar> // For mbstate_t
+++ |+#include <cstddef>
41 |
In file included from /usr/include/c++/10.2.0/bits/exception_ptr.h:40,
from /usr/include/c++/10.2.0/exception:147,
from /usr/include/c++/10.2.0/ios:39,
from /usr/include/c++/10.2.0/ostream:38,
from /usr/include/c++/10.2.0/iostream:39,
from error.cpp:3:
/usr/include/c++/10.2.0/new:126:26: error: declaration of ‘operator new’ as non-function
126 | _GLIBCXX_NODISCARD void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
| ^~~~~~~~
/usr/include/c++/10.2.0/new:126:44: error: ‘size_t’ is not a member of ‘std’; did you mean ‘size_t’?
126 | _GLIBCXX_NODISCARD void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
| ^~~~~~
I guess the fourth line does tell you that you missed a semicolon (if you have the patience to scroll to it), but it's not exactly clear where.#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
std::string decrypt(std::string& k, std::string& m) {
std::vector<std::string> c(k.length());
int n = m.length() % k.length() == 0 ? m.length() / k.length() : m.length() / k.length() + 1;
int a = 0;
for (std::string& s : c) {
for (int i = 0; i < n; i++) {
s += a >= m.length() ? ' ' : m[a];
a++;
}
}
std::vector<int> j(k.length());
std::iota(j.begin(), j.end(), 0);
std::sort(j.begin(), j.end(), [&k](int x, int y) { return k[x] < k[y]; });
std::vector<int> q(k.length());
for (int i = 0; i < k.length(); i++) {
q[j[i]] = i;
}
std::string r = "";
for (int i = 0; i < n; i++) {
for (int ii = 0; ii < k.length(); ii++) {
char h = c[q[ii]][i];
if (c != ' ') {
r += c;
}
}
}
return r;
}
int main() {
std::string k;
std::getline(std::cin, k);
std::string m;
std::getline(std::cin, m);
std::cout << decrypt(k, m) << std::endl;
}
Try it online!
The error message does tell you where the error is, but you have to scroll through 228 lines with over 22 kB of content.