2012-12-30 19 views
12

typeid(T).name(), yazının insan tarafından anlaşılabilir adını döndürmediğinden, şablon argümanlarının adını bir sınıfa yazdırmak istiyorsak bize fazla yardımcı olmaz şablon, özellikle hata ayıklama yaptığımızda. Sık sık hata ayıklama bu yazma gibi hissediyorum: Tüm şablon bağımsız değişkenleriyle birlikte güzel yazdırma türleri ve sınıf şablonu

print<Args...>(cout); //dump the names of all types to stdout! 

yüzden bana sınıf şablonunun adını verir oldukça desenli programı yazıyorum. Eh, bazı örnek kullanımı yoluyla bunu anlamak kolaydır: Dahili olarak

print<int>(cout);    //prints int 
print<int, double, char>(cout); //prints int, double, char 
print<std::string>(cout);  //prints std::basic_string<char, .. etc> 
print<std::wstring>(cout);  //prints std::basic_string<wchar_t, .. etc> 
print<X<int,Y<int>>>(cout);  //prints X<int, Y<int>> 

, ben şablon argüman olarak kendisine Y<int> geçerken bana "Y" döndüren template_name adında bir sınıf şablonunu kullanıyorum. Her kullanıcı sınıfı şablonu için kısmen uzmanlaşmıştır.

#define DEFINE_TEMPLATE_NAME(template_type) \ 
template<typename ... Ts>\ 
struct template_name<template_type<Ts...>>\ 
{\ 
    static const char* name()\ 
    {\ 
     return #template_type;\ 
    }\ 
}; 

Ve kullanıcı

onun şablon sınıfı kaydetmek için bu makro kullanmak için gereklidir gibidir: uzmanlaşma template_name<template_type<Ts...>> bunu demek türlerinde sadece üzerinde variadic sınıf şablonu, çünkü işleri

DEFINE_TEMPLATE_NAME(std::basic_string); 
DEFINE_TEMPLATE_NAME(std::vector); 
DEFINE_TEMPLATE_NAME(X); //X is a class template 
DEFINE_TEMPLATE_NAME(Y); //Y is a class template 

10 tüm şablon parametreleri türleri türleri olduğu sürece, sınıf şablonunun adı dönecektir. Aynı zamanda hem fonksiyon-tiplerini ve üye fonksiyonlu-tiplerini baskı yapabiliyor:

typedef void fun(int,int); 

//lets use snl::name() which returns name instead of printing! 
std::cout << snl::name<fun>(); //prints : void(int,int) 
std::cout << snl::name<fun*>(); //prints : void(*)(int,int) 

diğer dakikalık detayları ile the working code here bakınız. Şimdiye kadar harika çalışıyor.

Ama şimdi bu konuda iyileştirilmesi ve sivil türleri argümanlar sablona desteği eklemek istediğiniz ediyorum ve de karışık şablon argümanları:

template<int...> 
struct Z{}; 

//non-type template arguments : 1,2,3 
snd::print<Z<1,2,3>>(cout); //should print Z<1,2,3> 

//mixed template arguments : int, 100 
snd::print<std::array<int,100>>(cout); //should print std::array<int,100> 

Bunu nasıl yapardın? Böyle bir sınıf şablonunun ve argümanlarının adını genel olarak nasıl alabilirim?

+5

GCC, oldukça kullanışlı şablon sınıf adlarını yazdıran bir demangler ... –

+0

@KerrekSB: Evet, ama bu standart değil. Her yerde çalışan bir şey istiyorum. – Nawaz

cevap

6

Üzgünüm, bu bir "olumsuz cevap" (sorunuzun üstesinden geliyorum), ama korkarım bunu yapamazsınız. Hatta (örn template<int, int>, template<char, char, char>,) olmayan tip parametrelerin homojen listelerini kabul tek şablon sınıfları şartlarda sen bu tür bir uzmanlık gerekir:

template<typename T> 
struct single_type 
{ 
    // ... 
}; 

template<typename U, template<U...> class C, U... Us> 
struct single_type<C<Us...>> 
{ 
    // ... 
}; 

Bu uzmanlaşma, yasal ama işe yaramaz argüman türü nedeniyle U asla çıkarılabilir. En yaygın türlerin (int..., char..., vb.) Tekdüze listelerine yönelik özel uzmanlıkları tanımlayabilirsiniz, ancak karışık argümanların dizilimlerini de içeren heterojen tiplerin dizilerini kapsaması hala imkansız olacaktır.

Korkarım ki aradığınız şeyi elde etmek için yansımayı desteklemek için C++ 'yu beklemek zorundayız.