2014-01-03 4 views
5

У меня есть шаблон классаСтранных шаблонный класса специализация

template <class T> 
class A 
{ 
}; 

и очень странной специализация

template <> 
class A<class T*> : private A<void *> 
{ 
}; 

Кто-нибудь может объяснить смысл этой конструкции?

+0

Казалось бы, что специализация отображает любую инстанциацию с типом указателя на 'ничтожных *' случае, то есть шаблон должен рассматривать все типы указателей одинаково. – arne

+0

Это не кажется правильным. 'template <>' подразумевал бы, что для специализации нет параметров, но 'T' явно намеревается быть одним. –

+2

@ н.м. Это spezialisation для класса T; ' – hansmaad

ответ

4

обфускации объявляет класс T и специализировать шаблон для T *

#include <iostream> 

template <class T> 
class A 
{ 
    public: 
    static void f() { std::cout << "Template" << '\n'; } 
}; 

// Declare a class T and specialize the template for T* 
template <> 
class A<class T*> : private A<void *> 
{ 
    public: 
    static void f() { std::cout << "Specialization" << '\n'; } 
}; 

class T {}; 

int main() 
{ 
    // Template 
    A<int*>::f(); 
    // Specialization 
    A<T*>::f(); 
} 
4

Я думаю, что предполагаемый код будет:

template <class T> 
class A<T *> : public A<void*> 
{ 
}; 

То есть на частичную специализацию, которая будет использоваться для любой тип указателя, а не общий. То есть, всякий раз, когда A создается с использованием типа указателя, он будет использовать это замещение вместо общего.

Естественно, вы должны создать экземпляр, или в противном случае spezialize в A<void*>, перед тем это заявление, иначе вы будете иметь бесконечную рекурсию:

template class A<void*>; 

Это несколько общая идиома, чтобы заставить компилятор для повторного использования код. То есть вы знаете, что каждый экземпляр A<T*> в основном такой же, как и все указатели будут вести себя одинаково под капотом. Таким образом, вы предоставляете полный экземпляр A<void*>, а затем любой другой A<T*> наследует его, выполняя приведение в очередь, когда это необходимо.

С A<T*> наследует от A<void*>, он не должен предоставлять основную часть кода класса при его создании. Меньший код, мы надеемся, даст лучшую производительность.

Полный пример вперед, непроверенный:

template <typename T> 
class A 
{ 
    public: 
    A() 
    :m_data(0) 
    {} 
    void set(T x) 
    { m_data = x; } 
    T get() 
    { return m_data; } 
    //here there will be more complex operations 
    private: 
    T m_data; 
    //and a lot of data depending on T 
}; 

template class A<void*>; //splicit instantiation 

template <typename T> 
class A<T*> : public A<void*> 
{ 
    private: 
    typedef A<void*> base_type; 
    public: 
    //only the public, and maybe protected, functions are needed 
    //but the implementation is one-line each 
    void set(T *x) 
    { base_type::set(x); } 
    T *get() 
    { return static_cast<T*>(base_type::get()); } 
}; 
Смежные вопросы