Burada BOOST_TYPEOF uygulamasının genel fikrini anlamak isterim. Demek istediğim, kod tamam olabilir, ama sanırım gerçek Boost uygulamasında olduğu gibi kod basit olmayacak. Bu nedenle, BOOST_TYPEOF uygulaması fikrini anlamak isterim. Derleme zamanında bir ifadenin türünü anlamak için derleyici işlevleri (bazı API) kullanıyor mu?BOOST_TYPEOF nasıl uygulanır?
cevap
Çekirdekte, Boost :: Typontal, bir ifadenin türünü bir tamsayıya dönüştürmek için bir sizeof
değerlendirilmemiş bağlam kullanır ve sonra bir türe dönüştürür.
düşünün: Şimdi
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
, herhangi char
türüne veya bool
olarak değerlendirilen bir ifade verilmiş, biz yazabiliriz:
TYPEOF(expr) var = expr;
Boost :: typeof esasen bu düşüncenin bir genişleme 1997 yılında Brian Parker tarafından icat edilen; Bir tartışma ve fikrin tarihi için bkz. A Portable "typeof" Operator.
Şablonlar bu şema için bir problemdir; std::pair
kadar basit bir şey, özyinesinden önce bile, yazım alanının karesini verir. Boost :: typeof şablon türü ve derleme zamanı bağlantılı listenin ardışık yuvalara onun parametre çeşitlerini kodlayarak bu çözer:
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
Bu mevcut bir derleme zamanı bağlantılı liste uygulamasını varsayar. std::pair
kod çözücüsünün, parametre türleri için gereken şekilde liste yineleyicisinden çok öğe tükettiğini fark edeceksiniz; Bu, esas olarak, değiştirilemeyen tipte bir dilde eşdeğer fonksiyonel kodun doğrudan bir çevirisidir. ...
sayılı elips olarak işaretlenen iki satırda, türlerdeki sabit bir karmaşıklık seviyesiyle sınırlıyız (yani, çıkarılması istediğimiz bir tip oluşturan şablon ve tip sayısı) ile sınırlandırılmıştır. Boost :: Typeof'in bu limit için varsayılan değeri 50'dir, ancak verimliliği azaltmak ya da son derece karmaşık programlar için onu arttırmak için izin verir.
Bu, sizeof
'un bir derleme zamanı işleci olduğu ve şablon bağımsız değişkeni olarak kullanılabileceği fikrine dayanır. Bu şekilde her bir türe bir tamsayı atayabiliriz ve bu tamsayı türüne geri dönmek için kullanılabilir. Dezavantaj, her türün manuel olarak kaydedilmesi gerektiğidir.
Örn .:
#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';
}
Çıktı:
./test
int
- 1. schema.org includesIn nasıl uygulanır?
- 2. Set.toString() nasıl uygulanır?
- 3. LowPass Filtresi nasıl uygulanır?
- 4. AngularFireAuth nasıl düzgün uygulanır?
- 5. OpenID nasıl uygulanır?
- 6. Zamanlanmış döngü nasıl uygulanır?
- 7. 'Beğen' sistemi nasıl uygulanır
- 8. Bir MPVolumeView nasıl uygulanır?
- 9. ** Python'da nasıl uygulanır?
- 10. string.find, CPython'da nasıl uygulanır?
- 11. BigDecimal nasıl uygulanır?
- 12. Braintree escrow nasıl uygulanır
- 13. teradata sıralaması nasıl uygulanır
- 14. operatörü sil - nasıl uygulanır?
- 15. Django yamaları nasıl uygulanır
- 16. Üye türleri nasıl uygulanır?
- 17. "const" nasıl uygulanır?
- 18. Paralaks kaydırma nasıl uygulanır?
- 19. WPF'nin DependencyObject nasıl uygulanır?
- 20. DAO Scala'da Nasıl Uygulanır?
- 21. MonoTouch'da UISearchBar nasıl uygulanır
- 22. GWT'de HashMap nasıl uygulanır?
- 23. Java'da polimorfizm nasıl uygulanır?
- 24. Symbol.iterator nasıl uygulanır?
- 25. Minimal Denetleyici Nasıl Uygulanır
- 26. Neo4j kalıcılığı nasıl uygulanır?
- 27. C++ arayüzleri nasıl uygulanır?
- 28. Doğrulama nasıl uygulanır?
- 29. Java akışı nasıl uygulanır?
- 30. numpy.cov() işlevi nasıl uygulanır?
sayesinde size çok! TYPEOF hakkında (make_pair) ... Yani, tüm kombinasyonlar sadece 4 tür için yaptığınız gibi kabul edilir. Elbette hayır, buna benzer sonsuz kombinasyonlar var! O zaman nasıl yapılır? –
Narek
@Narek, şablonu ve parametrelerini derleme zamanı bağlantılı bir listede ardışık yuvalara kodlayarak yapılır. – ecatmur