Open Reputeless opened 5 years ago
よくある、ヘッダファイル以外をインクルードするとかは、データをコンパイル時に埋め込める便利な記法です。
int ar[] = {
#include "a.csv"
};
ヘッダファイル内で.cpp (相当のファイル) をインクルードするオプションを用意して、ヘッダオンリー化できるようにしているのとかは、ライブラリを作るにあたって設計選択のひとつになっています。
https://github.com/boostorg/chrono/blob/develop/include/boost/chrono/thread_clock.hpp
(最近はシングルヘッダ版を自動生成するとかもありますが)
プリプロセス関係だと、文字列リテラルの結合とかも、マイナーですがたまに便利ですね。自前のprintfやassertを作るときにも使いますし、長い文字列リテラルを分割して書くのにも便利です。
#include <cstdio>
#define INFO(fmt, ...) std::printf("[info] " fmt "\n" __VA_OPT__(,) __VA_ARGS__)
#define DEBUG(fmt, ...) std::printf("[debug] " fmt "\n" __VA_OPT__(,) __VA_ARGS__)
int main()
{
INFO("hello");
DEBUG("hello %d", 123);
}
#include <iostream>
int main()
{
std::string help = "The application is designed by ME.\n"
"Welcome my application";
std::cout << help << std::endl;
}
csvのインクルードとかを多用するようになると、以前私がブログに書いた以下のようなものがほしくなります。
コメントありがとうございます! 引き続き募集してます。
-->
演算子
#include <iostream>
int main()
{
int i = 10;
while (i --> 0)
{
std::cout << i << '\n';
}
}
template関数のオーバーロードに優先順位を付けるやつ:
#include<cstdint>
template<std::size_t N>struct priority : priority<N-1>{};
template<> struct priority<0>{};
#include<iostream>
#include<type_traits>
template<
typename T,
std::enable_if_t<std::is_same<std::decay_t<T>, float>::value, std::nullptr_t> = nullptr
>
void f_impl(T t, priority<1>){std::cout << "float " << t << std::endl;}
template<typename T>
void f_impl(T t, priority<0>){std::cout << "T " << t << std::endl;}
template<typename T>
void f(T&& t){f_impl(std::forward<T>(t), priority<1>{});}
int main(){
f(3.1);
f(3.14f);
f("3.141592");
}
面白いかは分からないですが、リテラル0だけを受け取る関数(nullptrからは目を逸らして・・・)
struct minus {
constexpr bool operator<(std::nullptr_t) {
return true;
}
constexpr bool operator>(std::nullptr_t) {
return false;
}
};
void f(std::nullptr_t) {
std::cout << "literal 0" << std::endl;
}
コンパイルできそうだけどできないコードたち
void f2(std::shared_ptr<int>=0);
void f(int*=0);
int a[3];
a[[]{return 0;}()];
false_v
を作らないでlambda式でif constexpr内のstatic_assertの評価を遅延させるやつ
#include <type_traits>
template <typename T>
void f(T)
{
if constexpr (std::is_same_v<T, int>)
{
// Tがintのときのみ評価される
static_assert([]{return false;}());
}
}
int main()
{
f(2.4);
f(3);
}
https://cpprefjp.github.io/lang/cpp17/if_constexpr.html https://github.com/cpprefjp/site/pull/577 by @alphya
input streamの中身をまるごとoutput streamにぶちこむやつ
os << is.rdbuf();
Most vexing parse: https://en.wikipedia.org/wiki/Most_vexing_parse
暗黙の型変換にやられるやつ(ただのバグ)
#include <iostream>
int main()
{
if(-1 < 1u)
{
std::cout << "-1 < 1u";
}
else
{
std::cout << "-1 > 1u";
}
}
名前空間の付け忘れにやられるやつ(ただのバグ)
#include <iostream>
#include <cmath>
int main()
{
//std::cout << std::abs(0.5); // 0.5
std::cout << abs(0.5); // 0
}
template <int>
int a = 0;
int main() {
//a<10>= 1; // 動かない
a<10> = 1;
}
スペースの有無で演算子と解釈されるかどうか異なります
(特別C++に限らないけけど) Fast inverse square root とか
https://wandbox.org/permlink/fXQKYqQAgMiyMMf9
constexprが普通に使えるこんにちは出番がなさそう・・・?
@zxc-key 提案ありがとうございます。
enum
をコンパイル時定数として扱うのは今では古いテクニック (現在は constexpr
) で、ある程度知られているとも思います_0 = 100
のようなコードで不正になります。magic_enum というライブラリの enum_count
では、複雑なテクニックでその問題も回避しています【面白いネタ的なコードや不思議な文法】として cppmap で新規に取り上げるネタはありませんでしたが、また面白いコードを見つけたら教えてください 🖐
int main()
{
[]{};
[]{}();
[](){};
[](){}();
[[]][]{};
[]()[[]]{};
[[]][]{}();
[[]][](){};
[]()[[]]{}();
[[]][](){}();
[[]][]()[[]]{};
[[]][]()[[]]{}();
}
ネタの一つとして提供:https://twitter.com/yohhoy/status/1367790416007897089
#include <iostream>
using T = int&;
void f(T&) { std::cout << "non-const" << std::endl; }
void f(const T&) { std::cout << "const" << std::endl; }
int main() {
int x;
f(x);
}
コンパイルできそうでできないやつです。
#include <type_traits>
using T = int&;
using T2 = const T&;
static_assert(std::is_same_v<T, T2>);
長い演算子 (演算子の優先順位的にできるやつ)
#include <iostream>
int main() {
int a = 10, b = 10;
a = a +-+-+-+-+-+-+-+-+ 6 +-+-+-+-+-+-+-+-+ 5;
b = b + + + + + + + + + 6 - - - - - - - - - 5;
std::cout << a << '\n';
std::cout << b << '\n';
return 0;
}
実用性はなくてもいいので、面白いネタ的なコードや不思議な文法、仕様のハックなどがあれば教えてください。ある程度たまったら記事にします。
(例) コメントアウトのトリック