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
/ class
C++ 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.