C ++ 14可変テンプレート:その目的は何ですか?任意の用途の例?
質問
c ++ 14はテンプレート化された変数の作成を可能にします。通常の例は、さまざまなタイプに対して数学的定数πの値を取得するために読み取ることができる変数 'PI'です(int
の場合は3。float
などで可能な最も近い値)
テンプレート化された構造体やクラス内で変数をラップするだけで、この機能を持つことができます。私はいくつかの重複を見ます。
およびPIの例以外の場合、それはどのように構成されていない変数で動作しますか?そのような特徴を最大限に活用する方法とその目的はどのようなものであるかを理解するための任意の使用例?
解決
PIの例以外、非コンストラクションでどのように機能するのでしょうか 変数?
現在、タイプの変数を別々にインスタンス化するようです。すなわち、10からn<int>
に割り当てることができ、テンプレートの定義とは異なります。
template<typename T>
T n = T(5);
int main()
{
n<int> = 10;
std::cout << n<int> << " "; // 10
std::cout << n<double> << " "; // 5
}
.
宣言がconst
の場合はreadonlyです。 constexpr
宣言のようにconstexpr
の場合は、constexpr
(Respolions)の外部にはあまり使用されていません。
それ以外にも、変数を折り返すだけでこの機能を持つことができます テンプレート化された構造体またはクラス内で、このミックスはタイプとどのように混在していますか 変換?
それは簡単な提案であることを意味しています。私はそれがタイプ変換にかなりの方法でどのように影響するかを見ることができません。すでに述べたように、変数の型はテンプレートをインスタンス化したタイプです。すなわち、decltype(n<int>)
はintです。 decltype((double)n<int>)
は2倍ほどです。
そのような機能を最大限に活用する方法を理解するための使用例 そしてその目的は何ですか?
N3651 は簡潔な根拠を提供します。
ALAS、既存のC ++ルールにテンプレート宣言を許可しない 変数を宣言します。これにはよく知られている回避策があります 問題:
•クラステンプレートのconstexpr静的データメンバーを使用する
•希望の値を返すConstexpr関数テンプレートを使用する
これらの回避策は、何十年もの間知られており、よく文書化されています。 STD :: Numeric_Limitsなどの標準クラスはArchPeypealicalです 例。これらの回避策は完璧ではありませんが、彼らの欠点です C ++ 03時代のみが単純であるため、ある程度許容された 組み込み型定数は、不具合の直接と効率的なものを楽しんだ コンパイル時間サポート。そのすべての採用により変更されました 直接的で効率的に拡張されたC ++ 11のconstexpr変数 ユーザー定義型の定数へのサポート。今、プログラマー プログラムでは、(クラスタイプの)定数をもっと見ています。 それでは、に関連する混乱や欲求不満を成長させます 回避策
...
「静的データメンバー」の主な問題は次のとおりです。
•「重複」宣言が必要です。クラスの中に1回 テンプレート、クラステンプレートの外側に「本物」を入力するためのテンプレート 定義コンデントがODR使用されている場合。
•プログラマは両方とも断熱して混同しています。 宣言。対照的に、「普通の」定数宣言は必要ありません 重複宣言
...
よく知られた例このカテゴリの例はおそらく静的メンバーです numeric_limitsの関数、またはそのような関数 Constexpr関数テンプレートは存在しません 静的データメンバーの「重複宣言」という問題がある 持ってる;さらに、それらは機能的抽象化を提供します。しかし、彼ら 定義サイトで、プログラマーに事前に選択されて、 定数は配信されます.const参照によって、またはによって 平らな非参照タイプ。 const参照によって配信された場合 定数は静的ストレージに体系的に割り当てられなければなりません。もしの場合 非基準タイプによって、定数はコピーが必要です。コピーしない 組み込み型の問題は、ユーザー定義のためのショーストッパーです。 小さな周りにラッパーではない値意味論を持つタイプ 組み込みタイプ(例えば、行列、または整数、またはbigfloatなど)によって コントラスト、「通常の」const(expr)変数はこれに悩まされません 問題。簡単な定義が提供され、その決定 定数が実際にストレージのみでレイアウトする必要があるかどうか 定義ではなく、使用量によって異なります。
他のヒント
テンプレート構造体またはクラス
内で変数をラッピングするだけで、この機能を持つことができます。
はい、しかしそれは無傷の塩の塩であろう。血圧には健康ではありません。
pi<double>
は、pi<double>::value
よりも優れた意図を伝えます。短くてポイントに。この構文を許可し奨励するのに十分な理由は十分なのです。
C ++ 14の可変テンプレートの他の実際の例は、std::accumulate
に何かを渡すための関数が必要な場合です。
template<typename T>
T const & (*maxer) (T const &, T const &) = std::max<T>;
std::accumulate(some.begin(), some.end(), initial, maxer<float>);
.
std::max<T>
を使用することは、正確な署名を推測できないため、不十分です。この特定の例では、代わりにmax_element
を使用できますが、この動作を共有する関数のクラス全体があることです。
これらの線に沿ったものが可能であるかどうか不思議に思う:(テンプレートラムダスの可用性を想定)
void some_func() {
template<typename T>
std::map<int, T> storage;
auto store = []<typename T>(int key, const T& value) { storage<T>[key] = value; };
store(0, 2);
store(1, "Hello"s);
store(2, 0.7);
// All three values are stored in a different map, according to their type.
}
.
今、これは便利ですか?
より単純な使用として、pi<T>
の初期化は明示的な変換(単項コンストラクタの明示的な呼び出し)を使用し、一様初期化を使用しないことに注意してください。つまり、Constructor radians
を持つタイプradians(double)
を指定して、pi<radians>
を書くことができます。
well、このようなコンパイルタイムコードを書くために使用することができます:
#include <iostream>
template <int N> const int ctSquare = N*N;
int main() {
std::cout << ctSquare<7> << std::endl;
}
.
これは同等の
に対する重大な改善です#include <iostream>
template <int N> struct ctSquare {
static const int value = N*N;
};
int main() {
std::cout << ctSquare<7>::value << std::endl;
}
.
可変テンプレートが導入される前にテンプレートメタルグラムを実行するために書き込むために使用した。非タイプ値の場合、C ++ 11はconstexpr
を使用しているため、これを実行できました。そのため、テンプレート変数には、変数テンプレートへのタイプに基づく計算を許可するという利点があります。
tl; DR:彼らは私たちが以前にしなかったことを何でもすることを許可していませんが、彼らはPitaを満たしているテンプレートをメタリングします。
ここでユースケースがあります。
template<typename CT> constexpr CT MARK = '%';
template<> constexpr wchar_t MARK<wchar_t> = L'%';
.
文字列処理テンプレートで使用されている`
template <typename CT>
void ProcessString(const std::basic_string<CT>& str)
{
auto&& markpos = str.find(MARK<CT>);
...
}
.