ここでは、BOOST_TYPEOFを実装する一般的な考え方を理解したいと思います。私はコードがOKかもしれないことを意味しますが、実際のBoostの実装ではコードが単純ではないと思います。したがって、BOOST_TYPEOF実装の考え方を理解したいと思います。コンパイル時に式の型を理解するためにコンパイラ関数(いくつかのAPI)を使用していますか?BOOST_TYPEOFの実装方法は?
答えて
コアでは、Boost :: Typeofはsizeof
評価されていないコンテキストを使用して式の型を整数に変換し、次にそれを型に変換します。
を考えてみましょう:今すぐ
template<int N> struct sizer { char value[N]; };
sizer<1> encode(char);
sizer<2> encode(unsigned char);
sizer<3> encode(signed char);
sizer<4> encode(bool);
...
template<int N> struct decode {};
template<> struct decode<1> { typedef char type; };
template<> struct decode<2> { typedef unsigned char type; };
template<> struct decode<3> { typedef signed char type; };
template<> struct decode<4> { typedef bool type; };
#define TYPEOF(expr) decode<sizeof(encode(expr))>::type
、あらゆるchar
タイプやbool
に評価される式を考えると、我々は書くことができます。
TYPEOF(expr) var = expr;
ブースト:: typeof演算は、基本的にこのアイデアを拡張したものです1997年にBrian Parkerによって最初に発明されたものです。アイデアの議論と歴史については、A Portable "typeof" Operatorを参照してください。
このスキームでは、テンプレートに問題があります。 std::pair
という単純なものは、再帰の前であっても型空間の2乗を与えます。ブースト:: typeof演算は、コンパイル時にリンクされたリストの連続するスロットにテンプレートタイプとそのパラメータの型を符号化することによって、これを解決:
template<typename List> struct sizer {
char item0[List::at<0>];
char item1[List::at<1>];
char item2[List::at<2>];
...
};
template<typename List> struct encode_type<List, char>: append<List, 1> {};
template<typename List> struct encode_type<List, unsigned char>: append<List, 2> {};
template<typename List, typename S, typename T>
struct encode_type<List, std::pair<S, T> >:
encode_type<encode_type<append<List, 99>, S>, T> {};
template<typename Iter> struct decode_type<1, Iter> {
typedef char type;
typedef Iter iter;
};
template<typename Iter> struct decode_type<2, Iter> {
typedef unsigned char type;
typedef Iter iter;
};
template<typename Iter> struct decode_type<99, Iter> {
typedef typename decode_type<Iter::next::value, Iter::next>::type S;
typedef typename decode_type<Iter::next::value, Iter::next>::iter S_iter;
typedef typename decode_type<S_Iter::next::value, S_Iter::next>::type T;
typedef typename decode_type<S_Iter::next::value, S_Iter::next>::iter T_iter;
typedef std::pair<S, T> type;
typedef T_iter iter;
};
template<typename List, typename T>
sizer<typename encode_type<List, T>::type> encode(const T&);
template<typename List> struct decode {
typedef typename decode_type<List::begin::value, List::begin>::type type; };
#define TYPEOF(expr) decode<list<
sizeof(encode(expr).item0),
sizeof(encode(expr).item1),
sizeof(encode(expr).item2),
...
> >::type
これは、既存のコンパイル時にリンクされたリストの実装を想定しています。 std::pair
のデコーダでは、パラメータの型に必要な数だけリストイテレータから項目を消費します。これは本質的に、変更不可能な型を持つ言語の同等の機能コードの直接の変換です。
省略記号...
としてマークされている2つの行では、タイプが一定の複雑さ(つまり、推測したいタイプを構成するテンプレートとタイプの数)に制限されています。 Boost :: Typeofのデフォルト値は50ですが、複雑なプログラムでは効率を上げるために減らしたり、効率を上げることができます。
sizeof
はコンパイル時の演算子であり、テンプレート引数として使用できるという考え方に基づいています。このようにして、各型に整数を代入することができ、その整数を使用して型に戻すことができます。欠点は、各タイプを手動で登録する必要があることです。
例えば:
#include <boost/preprocessor/stringize.hpp>
#include <cstddef>
#include <iostream>
template<size_t> struct TypeId;
#define REGISTER_TYPE(T, id) \
template<> struct TypeId<id> { \
char value[id]; \
typedef T type; \
static char const* const name; \
}; \
char const* const TypeId<id>::name = BOOST_PP_STRINGIZE(T); \
TypeId<id> type_to_id(T);
#define TYPEID_(value) TypeId<sizeof(type_to_id(value))>
#define TYPEOF(value) typename TYPEID_(value)::type
#define TYPENAME(value) TYPEID_(value)::name
REGISTER_TYPE(int, 1)
REGISTER_TYPE(unsigned int, 2)
// and so on for all built-in types
int main() {
int x;
TYPEOF(x) y;
std::cout << TYPENAME(y) << '\n';
}
出力:あなたは非常に多くの
./test
int
- 1. オプションリストの実装方法は?
- 2. NetworkManagersの実装方法は?
- 3. ストラテジーデザインパターンの実装方法は?
- 4. SimpleMiddlewareの実装方法は?
- 5. jScrollの実装方法は?
- 6. インタフェースの実装方法は
- 7. リモートコントロールアプリケーションの実装方法は?
- 8. __delitem__メソッドの実装方法は?
- 9. ツールバーの実装方法は?
- 10. データヒストリアンの実装方法は?
- 11. メッセージシステムの実装方法は?
- 12. シングルサインオン - 実装方法
- 13. IDropSourceNotify - 実装方法
- 14. IdentityServer4 - 偽装の実装方法
- 15. RecycleViewのマルチビュータイプの実装方法は?
- 16. このスライドナビゲーションメニューの実装方法は?
- 17. このgitignoreシナリオの実装方法は?
- 18. 次のアニメーションの実装方法は?
- 19. WatchKitのスライドボタンの実装方法は?
- 20. containsAllメソッドの実装方法
- 21. if-elseの実装方法
- 22. GestureListener.onFling()メソッドの実装方法
- 23. jspブラウザアクションの実装方法
- 24. Sencha Pickerの実装方法
- 25. JavaScriptデザインパターンの実装方法
- 26. .NETデータセットの実装方法
- 27. バックオフィスコントローラの実装方法
- 28. スタック実装Trollfaceの方法
- 29. Android:テンキーパッドの実装方法
- 30. jQueryの実装方法[]
ありがとう! TYPEOF(make_pair)についてどういうことですか...あなたは、4種類のタイプのすべての組み合わせが考慮されることを意味しますか?もちろん、いいえ、これに似た無限の組み合わせがあります!そしてそれはどのように行われますか? –
Narek
@ Narekこれは、テンプレートとそのパラメータをコンパイル時のリンクリストの連続するスロットにエンコードすることによって行われます。 – ecatmur