ポエム
std::forward
std::forward
は、関数テンプレートであるにも関わらずテンプレート引数を指定する必要があります。しかし、テンプレート引数はだいたい std::forward<decltype(a)>(a)
のような感じで書くと思います。個人的に、これは std::forward
をラップして、
// You can write forward without template argument. template <typename T> [[nodiscard]] constexpr T && forward(T && arg) noexcept { return std::forward<decltype(arg)>(arg); }
のようにしておけば、forward(arg)
のようにテンプレート引数の指定なしで書けるのでいいのではないかと思っています。
[追記]と、思っていた時期もあったのですが、どうやらダメみたいです... ↓参照
c++ - Why is template argument deduction disabled with std::forward? - Stack Overflow
命名規則
キャメルケース、スネークケースなどがありますが、個人的には全部小文字のスネークケースがよいのではないかと思います。なぜなら、全部小文字の場合にはフォーマッタなどでキャメルケースなどに変換することが容易だからです。型は大文字、などとして大文字小文字で区別すると、SomeType sometype;
のように単純に小文字に変換することができない場合があります。その点、型も変数も小文字で統一すると、このようなことがなくスムーズに命名規則を変換できがちです。
また、クラスのプライベートメンバを m_
から始まるようにすると、コード補完が効いて便利です。_
始まりだとグローバルにある標準の関数が大量にリストアップされます... 末尾は _
をつけてもつけなくても変わらないと思います。つけたほうがちょっとかっこいいかもしれません。(個人の感想です...)
コメント
コメントを書くときに日本語で書くと絶対に文字化けします。これは真理です。
書くことがなさすぎるので、自作ライブラリの紹介をします
初めに
このブログは作ってみたものの、特に書くこともなく放置していました() なので、いつか書こうと思っていた自作ユーティリティーのドキュメントなどを書こうと思います。
nyaruga::util::diff
今回は、関数を微分する関数を紹介します。nyaruga::util::diff
です。
nyaruga_util/diff.hpp at master · alphya/nyaruga_util · GitHub
using num_t = boost::multiprecision::number<boost::multiprecision::cpp_dec_float<1000>>; // 微分します // 7 点近似です template <typename Number = num_t, typename F> constexpr auto diff(F && f) noexcept { return [f](auto && x) noexcept(noexcept(f(x))) -> Number { auto h = 1e-7; if constexpr (std::is_same_v<Number, num_t>) h = DBL_EPSILON; auto&& y1 = f(static_cast<Number>(x + h)); auto&& y2 = f(static_cast<Number>(x - h)); auto&& y3 = f(static_cast<Number>(x + 2 * h)); auto&& y4 = f(static_cast<Number>(x - 2 * h)); auto&& y5 = f(static_cast<Number>(x + 3 * h)); auto&& y6 = f(static_cast<Number>(x - 3 * h)); return (y5 - 9 * y3 + 45 * y1 - 45 * y2 + 9 * y4 - y6) / (60 * h); }; }
上記の関数は、一引数の関数を引数にとって、「点x
での微分係数を返すような関数」を返す高階関数です。7 点近似らしいです。導出などは、検索すればおそらく見つけられると思われます() (自分でも、これでよいのかわかってないです。もっと良いやり方をご存じの方は教えてください...orz)
ちなみに、h の値も雰囲気で決定しました☆orz
使い方
int main() { auto fn = [](double x){ return std::pow(x, 2); }; // テンプレート引数は、関数の引数の型などに合わせてください auto d_fn_d_x = diff<double>(fn); std::cout << d_fn_d_x(3); // 6 }
nyaruga::util::partial_diff
せっかくなので、偏微分する関数も紹介します。
nyaruga_util/partial_diff.hpp at master · alphya/nyaruga_util · GitHub
namespace hana = boost::hana; // Partial differentiation template <std::size_t count, typename NumType = num_t, typename F> constexpr auto partial_diff(F && f) noexcept { return [f](auto&& ... args) noexcept -> NumType { return diff<NumType>(bind_select_arg_replace<count>(forward(f), args...)) (hana::arg<count>(forward(args)...)); }; }
テンプレート引数 count で、( 1 からスタートして)何番目の引数に関して偏微分するかを指定します。
bind_select_arg_replace<count>
は、count で指定した引数をプレースホルダーにするように、与えられた引数を引数の関数に束縛するような高階関数です。こうして一引数関数を作り、diff
関数でその引数に関して微分しています。
使い方
int main() { auto lambda = [](auto ... a) { return static_cast<nyaruga::util::num_t>((a * ... )); }; std::cout << std::setprecision(18) << nyaruga::util::partial_diff<1>(lambda)(nyaruga::util::num_t(2), 5., 6.); // 30 }
おわりに
すごく手抜き気味になってしまいましたが、たぶんこの記事は誰も見ないと思って公開しようと思います...
std::string を空白で分割する
std::sregex_token_iterator を使う
例として、
双方向連結リスト | アルゴリズムとデータ構造 | Aizu Online Judge
をやった
#include <iostream> #include <list> #include <string> #include <regex> #include <algorithm> class my_list : public std::list<int> { std::regex m_separator{" "}; // 分割用のセパレータ public: using std::list<int>::list; // std::listのコンストラクタ群のmy_listでの暗黙定義 void accept_command(const std::string & line) { // セパレータで入力を分割し、イテレータ it で参照できるようにしています auto && it = std::sregex_token_iterator(std::begin(line), std::end(line), m_separator, -1); // コマンドを command に入れています const std::string & command = *it; if (command == "insert") { // コマンドの数字を num に入れています auto && num = std::stoi(*std::next(it)); emplace_back(num); } else if (command == "delete") { auto && num = std::stoi(*std::next(it)); erase(std::find_if(begin(), end(), [&num](auto && tmp) {return tmp == num; })); } else if (command == "deleteFirst") pop_front(); else if (command == "deleteLast") pop_back(); else std::cout << "コマンド名をチェックしてください"; } }; template<typename T> void show(T && tmp) { for (auto && i = tmp.rbegin(); i != tmp.rend(); ++i) { std::cout << *i; if (i != std::prev(tmp.rend())) std::cout << " "; } } int main() { std::string s; std::getline(std::cin, s); const int & line_num = stoi(s); my_list m; for (auto i = 0; i < line_num; ++i) { std::getline(std::cin, s); m.accept_command(s); } show(m); }
C++ とても長い変数宣言
長い誰の役にも立たない変数宣言をしただけ
#include <iostream> template <typename T> [[maybe_unused]] volatile static const constexpr unsigned long long int ***** a = static_cast<const volatile long long unsigned int*****>(0); int main() { std::cout << a<void> << "\n"; // 0 }
nimっていうプログラミング言語があるらしい
おもしろそう。
Hello, World
echo "Hello, World!"