コンピュータサイエンスには2つの難しい問題があります。キャッシュの無効化、名前の付け方、オフバイワンエラーです。
これは2番目の問題、つまり名前の付け方についてです。
このテクニックまたはタイプがすでにどこかで使用されており、名前が付けられているかどうかを確認しています。 dichotomy
は問題ありませんが、bools_at_compile_time
は恐ろしい名前です。
using dichotomy_t = std::variant<std::false_type, std::true_type>;
// (or a struct that inherits from that, and overloads operator bool())
constexpr dichotomy_t dichotomy( bool b ) {
if (b) return std::true_type{};
return std::false_type{};
}
template<class F, class...Bools>
constexpr auto bools_at_compile_time( F&& f, Bools...bools ) {
static_assert( (std::is_same<Bools, bool>{} && ...) );
return std::visit( std::forward<F>(f), dichotomy(bools)... );
}
dichotomy_t
は、trueとfalseの間のバリアントです。そのランタイム表現は0
または1
です。
これにより、次のことが可能になります。
auto foo( bool x, bool y ) { // <-- x and y are run-time bools here
auto func = [&](auto x, auto y) {
return some_template<x,y>(); // <-- x and y are compile-time bools here
};
return bools_at_compile_time( func, x, y ); // <-- converts runtime to compile time bools
}
dichotomy_t
またはもっと一般的なbools_at_compile_time
の名前はありますか?任意のコミュニティ(C++以外のコミュニティでも)でよく知られている名前を探しています。「ランタイム値を取得し、生成されたコードでスイッチとコンパイル時の値のセットを作成して、どちらかを選択する」 "文よりも優れています。
良い答えは、名前、その名前の意味を説明する引用/引用、他のコンテキストで使用されているその名前付きの事物の例、およびこの名前が上記のタイプ/値および関数と同等または包括的であることの証拠を含みます。
(名前を見つけるのに役立つかもしれません。これの一般化は、既知の状態の数が固定されているenum
ではなくbool
であり、ランタイムを変換するスイッチ/ケースマップです。各case句のコンパイル時定数に値を入力します。)
このパターンの既存の名前は知りませんが、STLがどのように名前を付けているかをよく見る場合は、コードを明示的にするのに十分近い名前を使用できます。
@ Jarod42の_dispatcher_t
_のアイデアも気に入りました。_dichotomy_t
_や_n_chotomy_t
_よりも汎用的だと思います。
dichotomy()
はmake_variant(b)
と呼ぶことができます。引数で指定されたブール値の_std::variant
_値を返すためです。 _std::make_Tuple
_と同じように、複数の引数からタプルを作成します。
_bools_at_compile_time
_を_static_eval
_に置き換えることをお勧めします。 _static_assert
_のように、コンパイル時にアサーションを作成します。
eval
がユースケースに適した形容詞でない場合は、簡単に_static_*
_に変更できます。
_#include <type_traits>
#include <variant>
#include <utility>
using dichotomy_t = std::variant<std::false_type, std::true_type>;
// (or a struct that inherits from that, and overloads operator bool())
constexpr dichotomy_t make_variant( bool b ) {
if (b) return std::true_type{};
return std::false_type{};
}
template<class F, class...Bools>
constexpr auto static_eval( F&& f, Bools...bools ) {
static_assert( (std::is_same<Bools, bool>{} && ...) );
return std::visit( std::forward<F>(f), make_variant(bools)... );
}
template<bool x, bool y>
auto some_template() {
return x || y;
}
auto foo( bool x, bool y ) { // <-- x and y are run-time bools here
auto func = [&](auto x, auto y) {
return some_template<x,y>(); // <-- x and y are compile-time bools here
};
return static_eval( func, x, y ); // <-- converts runtime to compile time bools
}
#include <iostream>
int main() {
std::cout << foo( true, true ) << "\n";
}
_
関数の特殊なバージョンの生成はcloningと呼ばれます。 ( 手順の複製 を参照)。 cloneという用語は、定数の伝播中にオプティマイザによって生成される特殊化された関数に名前を付けるために使用されます( gcc doc を参照)。
std::visit
によって生成される特殊な関数のセットには、clone setという名前を付けることができます。
このセットは、引数値のすべての combinations に対して生成されます。この項combinationでは、各引数の可能な値のセットが有限であると仮定します。
したがって、引数値のすべての組み合わせのクローンのセットなど、クローンのセットに長い名前を付けることができます。 コンビナトリアルクローンセットである可能性があります。
すでに指摘したように、引数に関して呼び出す適切な関数を選択するアクションは、dispatchと呼ばれます。
だから私はcombinatiorial_clone_set_dispatch
またはdispatch_in_combinatorial_clone_set
を提案します...
私は同様の実装を知らないので、バイクシェッドの色を使ってタイプごとに行きます。
using boolean_t = std::variant<std::false_type, std::true_type>;
これは、trueまたはfalseのstd::integral_constant
sのいずれかを格納できるバリアントであるため、自明です。 bool
のようなものですが、bool_t
は混乱を招く可能性があります。代替案はboolean_variant
ですが、これは冗長すぎる可能性があります。
constexpr boolean_t to_boolean_t( bool b ) {
if (b) return std::true_type{};
return std::false_type{};
}
私はconvert_bool
から始めましたが、少し一般的すぎます。 to_boolean_t
はより表現力があります。 make_boolean_t
も基本的にboolean_t
ファクトリ関数であるため、可能性があります。注:以前はto_constexpr_boolean
を選択しましたが、これは不必要に冗長です。
template<class F, class...Bools>
constexpr auto static_eval( F&& f, Bools...bools ) {
static_assert( (std::is_same<Bools, bool>{} && ...) );
return std::visit( std::forward<F>(f), to_boolean_t(bools)... );
}
Clonkの推論が好きなので、ここでstatic_eval
を選択しましたが、C++では "静的"は状況に応じた意味を持つため、代替案は(重要度の低い順)です。
boolean_visit
static_visit
constexpr_eval
constexpr_visit
あなたの問題は:(太字)
私は、どのコミュニティでもよく知られている名前(C++以外の名前でも)、「ランタイム値を取得してスイッチとコンパイル時の値のセットを生成で作成)を表す動詞も探しています選択するコード文よりも優れています。
ありますが、関連する科学分野からそれを採用する場合に限ります。
US National Electrical Code(NEC)は、配電盤を「大きな単一のパネル、フレーム、または表面、背面、またはその両方に取り付けられたパネルのアセンブリ、スイッチ、過電流およびその他の保護装置、バス、そして通常は楽器」。配電盤の役割は、配電盤に供給される電流をより小さな電流に分割してさらに分配し、これらのさまざまな電流にスイッチング、電流保護、および(場合によっては)メータリングを提供することです。一般に、配電盤は、変圧器、配電盤、制御機器、そして最終的には個々のシステム負荷に電力を分配します。
この考え方を採用すると、単純にswitchesと呼びます。
タイプ/変数名でストレージタイプやcv-qualifierなどを指定することは非常にまれであることも追加します(つまりrepeat)-直接目に見えない場合でも、それを強調する必要がない限り、通常は暗黙的にします。
多分staticCastValue?あなたが動的(ランタイム)値を静的値にキャストしているように。さまざまなタイプのテンプレートまたはオーバーロードで使用できます。
それともassertInmutable?のように、可変型を不変型に変換しています。
またはおそらく常に表現しますか?あなたと同じように、同じ値を一定の形で表現しています。 constexprに似た形式。
野生のもの:staticBifurcate?そこから選択する2つのことがあるように、分岐があります。
分岐動詞/ ˈbʌɪfəkeɪt/1. 2つの分岐または分岐に分割します。 「カイロ川のすぐ下で川が二股に分かれる」
または最後にconvertToConstExpr?値はconstexprと類似または互換性のあるものに変換されることを明示的に述べます。