LoginSignup
3
1

More than 3 years have passed since last update.

min/maxみたいな関数の呼び出し

Last updated at Posted at 2019-12-10

これはC++ Advent Calendar 201911日目の記事です

昨日は@segurさんのC++版FBX SDK入りのDockerイメージを作ってみるでした

このエラー結構遭遇しますよね?

std::minとかstd::max std::clampのように関数の引数が

template <class T>
T hoge(T x1, T x2, ...);

template <class T>
T huga(std::initializer_list<T> t);

みたいになっている場合の関数でこんな呼び出しをしたいことが結構ある

double x = ...;
x = std::clamp(x, 0, 1); // xを[0,1]に収めたい

しかしこれだとTが推論できなくてコンパイルエラーになる

prog.cc:6:9: error: no matching function for call to 'clamp'
    x = std::clamp(x, 0, 1);
        ^~~~~~~~~~
/opt/wandbox/clang-head/include/c++/v1/algorithm:2649:1: note: candidate template ignored: deduced conflicting types for parameter '_Tp' ('double' vs. 'int')
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi)
^
/opt/wandbox/clang-head/include/c++/v1/algorithm:2638:1: note: candidate function template not viable: requires 4 arguments, but 3 were provided
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp)
^

オーバーロードが多いstd::minとかだと結構な数のエラーが出る
https://wandbox.org/permlink/xXkJXYMNqMW7PI3d

そして仕方なくこんな感じの対処をすることが多い

std::clamp(x, 0., 1.); // 小数点をつけて浮動小数点リテラルに変更した

でもさ

リテラルだったらいいけど何か変数だったときがめんどくさい

int l = ..., h = ...;

std::clamp(x, static_cast<double>(l), static_cast<double>(h));

int y = ...;
float z = ...;
std::min({x, static_cast<double>(y), static_cast<double>(z)});

え?C言語スタイルのキャストなら短く書ける?またまたご冗談を

推論できないなら

推論させなければいいじゃない

std::clamp<double>(x, l, h);

簡潔だし戻り値の型がハッキリしてるのもよい

initializer_listの方も問題なく使える

std::min<double>({x, y, z});

ただし縮小変換に伴う警告はしっかり出るのでそこら辺で結局キャストをそこそこ使うような気もする(でもこの場合だと出ない。c++って難しい)

参考までに

std::gcd std::lcmはテンプレート引数が2つに分かれているので今回の例には当てはまらない(符号の有る無しで結果を分けてるみたい)

明日は

@kizulさんのC/C++間での翻訳フェーズの違い です

3
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1