Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++ の面白いコード、トリッキーなコードの話 #9

Open
Reputeless opened this issue Mar 12, 2019 · 21 comments
Open

C++ の面白いコード、トリッキーなコードの話 #9

Reputeless opened this issue Mar 12, 2019 · 21 comments
Labels

Comments

@Reputeless
Copy link
Member

実用性はなくてもいいので、面白いネタ的なコードや不思議な文法、仕様のハックなどがあれば教えてください。ある程度たまったら記事にします。

  • 数行~十数行で完結するぐらいが好ましいです
  • マイナーなものでも有名なものでも OK です

(例) コメントアウトのトリック

@faithandbrave
Copy link
Contributor

よくある、ヘッダファイル以外をインクルードするとかは、データをコンパイル時に埋め込める便利な記法です。

int ar[] = {
    #include "a.csv"
};

ヘッダファイル内で.cpp (相当のファイル) をインクルードするオプションを用意して、ヘッダオンリー化できるようにしているのとかは、ライブラリを作るにあたって設計選択のひとつになっています。

https://github.com/boostorg/chrono/blob/develop/include/boost/chrono/thread_clock.hpp

(最近はシングルヘッダ版を自動生成するとかもありますが)

@faithandbrave
Copy link
Contributor

プリプロセス関係だと、文字列リテラルの結合とかも、マイナーですがたまに便利ですね。自前の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;
}

@faithandbrave
Copy link
Contributor

csvのインクルードとかを多用するようになると、以前私がブログに書いた以下のようなものがほしくなります。

@Reputeless
Copy link
Member Author

コメントありがとうございます! 引き続き募集してます。

--> 演算子

#include <iostream>

int main()
{
	int i = 10;

	while (i --> 0)
	{
		std::cout << i << '\n';
	}
}

@wx257osn2
Copy link
Contributor

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");
}

Wandbox

@onihusube
Copy link
Contributor

onihusube commented Mar 12, 2019

面白いかは分からないですが、リテラル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;
}

https://wandbox.org/permlink/sDe2GzeQuPk1hMT0

@Fuyutsubaki
Copy link
Contributor

コンパイルできそうだけどできないコードたち

void f2(std::shared_ptr<int>=0);
void f(int*=0);
int a[3];
a[[]{return 0;}()];

https://wandbox.org/permlink/P76EMNyoE6FAQaDs

@yumetodo
Copy link
Contributor

yumetodo commented Mar 13, 2019

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
cpprefjp/site#577
by @alphya

@yumetodo
Copy link
Contributor

input streamの中身をまるごとoutput streamにぶちこむやつ

os << is.rdbuf();

@rhysd
Copy link
Contributor

rhysd commented Mar 14, 2019

Most vexing parse: https://en.wikipedia.org/wiki/Most_vexing_parse

@agehama
Copy link

agehama commented Mar 14, 2019

暗黙の型変換にやられるやつ(ただのバグ)

#include <iostream>

int main()
{
    if(-1 < 1u)
    {
        std::cout << "-1 < 1u";
    }
    else
    {
        std::cout << "-1 > 1u";
    }
}

@agehama
Copy link

agehama commented Mar 14, 2019

名前空間の付け忘れにやられるやつ(ただのバグ)

#include <iostream>
#include <cmath>

int main()
{
    //std::cout << std::abs(0.5); // 0.5
    std::cout << abs(0.5);        // 0
}

@nekko1119
Copy link
Contributor

template <int>
int a = 0;

int main() {
    //a<10>= 1; // 動かない
    a<10> = 1;
}

スペースの有無で演算子と解釈されるかどうか異なります

@Fuyutsubaki
Copy link
Contributor

(特別C++に限らないけけど) Fast inverse square root とか

@zxc-key
Copy link

zxc-key commented Oct 27, 2020

https://wandbox.org/permlink/fXQKYqQAgMiyMMf9

  • enumをコンパイル時定数として使う
  • enumの最後の要素を要素数として使う
  • 配列の変数名とインデックスを逆にしても動作する

@yumetodo
Copy link
Contributor

constexprが普通に使えるこんにちは出番がなさそう・・・?

@Reputeless
Copy link
Member Author

@zxc-key 提案ありがとうございます。

  1. enum をコンパイル時定数として扱うのは今では古いテクニック (現在は constexpr) で、ある程度知られているとも思います
  2. 「最後尾 = 要素数」は、サンプルコードでいうと _0 = 100 のようなコードで不正になります。magic_enum というライブラリの enum_count では、複雑なテクニックでその問題も回避しています
  3. cppmap 掲載済みです https://cppmap.github.io/articles/it-compiles/#_2

【面白いネタ的なコードや不思議な文法】として cppmap で新規に取り上げるネタはありませんでしたが、また面白いコードを見つけたら教えてください 🖐

@yohhoy
Copy link
Contributor

yohhoy commented Mar 5, 2021

int main()
{
  []{};
  []{}();
  [](){};
  [](){}();
  [[]][]{};
  []()[[]]{};
  [[]][]{}();
  [[]][](){};
  []()[[]]{}();
  [[]][](){}();
  [[]][]()[[]]{};
  [[]][]()[[]]{}();
}

ネタの一つとして提供:https://twitter.com/yohhoy/status/1367790416007897089

@yaito3014
Copy link

#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);
}

コンパイルできそうでできないやつです。

@yumetodo
Copy link
Contributor

yumetodo commented Mar 7, 2021

#include <type_traits>
using T = int&;
using T2 = const T&;
static_assert(std::is_same_v<T, T2>);

なるほど・・・?
https://wandbox.org/permlink/SVngPcUtKYXAL72O

@Ryoga-exe
Copy link

長い演算子 (演算子の優先順位的にできるやつ)

#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;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests