modern cpp tricks
1.0.0
これは、インタビューと競争力のあるプログラミングのコーディングでよく使用される最新のCPPトリックのリストです。
Rachitの作品が好きなら、
min(x, min(y, ...))s.contains vs s.find(...) != s.endmultiset.extract vs multiset.erase(multiset.find(...)) min(x, min(y, ...))初期化のリストとstd::min and std::maxを使用して、ライフを簡単にする
small = min(x, min(y, min(z, k))); // the old way
small = min({x, y, z, k}); // life is easy pair< int , int > cur = { 1 , 2 };
auto [x, y] = cur;
// x is now 1, y is now 2
// no need of cur.first and cur.second
array< int , 3 > arr = { 1 , 0 , - 1 };
auto [a, b, c] = arr;
// a is now 1, b is now 0, c is now -1 ポイントまでまっすぐに、私はしばしば、変数名とその値を描いたdebugマクロを使用しました。
# define deb ( x ) cout << #x << " " << x
int ten = 10 ;
deb (ten); // prints "ten = 10"これは多くの場合、デバッグに役立ちます。
ただし、ログする複数の変数がある場合、より多くのdeb2およびdeb3マクロになります。
# define deb ( x ) cout << #x << " " << x
# define deb2 ( x ) cout << #x << " " << x << " " << #y << " " << y
# define deb3 ( x, y, z ) cout << #x << " " << x << " " << #y << " " << y << " " << #z << " " << z これはスケーラブルではありません。
これが、バリアードマクロと折り畳み式を使用したソリューションです。
# define deb (...) logger(#__VA_ARGS__, __VA_ARGS__)
template < typename ...Args>
void logger (string vars, Args&&... values) {
cout << vars << " = " ;
string delim = " " ;
(..., (cout << delim << values, delim = " , " ));
}
int xx = 3 , yy = 10 , xxyy = 103 ;
deb (xx); // prints "xx = 3"
deb (xx, yy, xxyy); // prints "xx, yy, xxyy = 3, 10, 103" template < typename ... T>
void read (T &...args) {
((cin >> args), ...);
}
template < typename ... T>
void write (string delimiter, T &&...args) {
((cout << args << delimiter), ...);
}
template < typename T>
void readContainer (T &t) {
for ( auto &e : t) {
read (e);
}
}
template < typename T>
void writeContainer (string delimiter, T &t) {
for ( const auto &e : t) {
write (delimiter, e);
}
write ( " n " );
} // Question: read three space seprated integers and print them in different lines.
int x, y, z;
read (x, y, z);
write ( " n " , x, y, z);
// even works with variable data types :)
int n;
string s;
read (n, s);
write ( " " , s, " has length " , n, " n " );
// Question: read an array of `N` integers and print it to the output console.
int N;
read (N);
vector< int > arr (N);
readContainer (arr);
writeContainer ( " " , arr); // output: arr[0] arr[1] arr[2] ... arr[N - 1]
writeContainer ( " n " , arr);
/* *
* output:
* arr[0]
* arr[1]
* arr[2]
* ...
* ...
* ...
* arr[N - 1]
*/ template < typename ...T>
void printer (T&&... args) {
((cout << args << " " ), ...);
}
int age = 25 ;
string name = " Rachit " ;
printer ( " I am " , name, ' , ' , age, " years old " );
// ^ This prints the following
// I am Rachit, 25 years old template < typename F>
auto debug_func ( const F& func) {
return [func]( auto &&... args ) { // forward reference
cout << " input = " ;
printer (args...);
auto res = func (forward< decltype (args)>(args)...);
cout << " res = " << res << endl;
return res;
};
}
debug_func (pow)( 2 , 3 );
// ^ this automatically prints
// input = 2 3 res = 8次のように、別のデコレーターbeautify 。
template < typename F>
auto beautify ( const F& func) {
return [func]( auto &&... args ) { // forward reference
cout << " ======== " << endl;
func (forward< decltype (args)>(args)...);
cout << " ======== " << endl;
};
}
beautify (debug_func(pow( 2 , 3 )));
// ^ this now prints
// ========
// input = 2 3 res = 8
// ========そのような一般的なデコレーターを書いてそれらをネストすることで、あなたがどれだけできるかは驚くべきことです。
特定の関数にかかった時間を計算するlog_timeのようなデコレーターについて考えてください。
s.contains vs s.find(...) != s.end set<int> example{1, 2, 3, 4};
example.find(3) != example.end() // true
example.contains(3) // true
これはmapとsetで動作することに注意してください。
multiset.extract vs multiset.erase(multiset.find(...)) multiset<int> mset{1, 1, 2, 2, 3, 3};
mset.erase(1); // {2, 2, 3, 3} deleted all 1s
mset.erase(mset.find(2)) // {2, 3, 3} need to use erase + find
mset.extract(3) // {2, 3} simple and clean
multiset::extract単一のインスタンスを自然に削除するのに役立ちます。setとmapでも動作します。