Можно сделать частичную специализацию членов шаблона класса
От: Zzealot Украина  
Дата: 20.12.09 20:59
Оценка:
Вопрос такой — есть ли какой-то способ при создании специализации шаблона класса (полной или частичной — неважно) описывать (definition) не все члены класса, а только те, которые меняются по отношению к первичному шаблону ?
Смотрел примеры в книгах — класс переписывают целиком — это ведь куча лишней работы ! А если мне требуется специализировать (модифицировать) только один из десяти методов класса ?
В стандарте ISO 14882-2003 (действующий стандарт С++) в разделе 14.7.3 (Explicit specialization) описывается синтаксис специализации отдельных членов класса:

template<class T1> class A {
template<class T2> class B {
template<class T3> void mf1(T3);
void mf2();
};
};

template<> template<class X>
class A<int>::B { };
template<> template<> template<class T>
void A<int>::B<double>::mf1(T t) { } //
// Здесь компайлер выдает ошибку: error C2039: 'mf1' : is not a member of 'A<T1>::B<X>'

Вместе с тем, на одном из сайтов
http://www.codersource.net/cpp_class_templates_specialization.html
прочитал, что если шаблон специализирован для какого-то типа, то все его члены должны быть описаны с использованием этого типа.

И чем глубже копаю, тем темнее становиться. Хотелось бы услышать мнение уважаемой общественности по этому вопросу.

Рукавишников Дмитрий aka Zzealot
Re: Можно сделать частичную специализацию членов шаблона кла
От: Faust Россия  
Дата: 20.12.09 23:45
Оценка:
Здравствуйте, Zzealot, Вы писали:

Z>Вопрос такой — есть ли какой-то способ при создании специализации шаблона класса (полной или частичной — неважно) описывать (definition) не все члены класса, а только те, которые меняются по отношению к первичному шаблону ?

Z>Смотрел примеры в книгах — класс переписывают целиком — это ведь куча лишней работы ! А если мне требуется специализировать (модифицировать) только один из десяти методов класса ?
Z>В стандарте ISO 14882-2003 (действующий стандарт С++) в разделе 14.7.3 (Explicit specialization) описывается синтаксис специализации отдельных членов класса:

Z>template<class T1> class A {

Z>template<class T2> class B {
Z>template<class T3> void mf1(T3);
Z>void mf2();
Z>};
Z>};

Z>template<> template<class X>

Z>class A<int>::B { };
Z>template<> template<> template<class T>
Z>void A<int>::B<double>::mf1(T t) { } //
Z>// Здесь компайлер выдает ошибку: error C2039: 'mf1' : is not a member of 'A<T1>::B<X>'

Z>Вместе с тем, на одном из сайтов

Z>http://www.codersource.net/cpp_class_templates_specialization.html
Z>прочитал, что если шаблон специализирован для какого-то типа, то все его члены должны быть описаны с использованием этого типа.

Z>И чем глубже копаю, тем темнее становиться. Хотелось бы услышать мнение уважаемой общественности по этому вопросу.


Z>Рукавишников Дмитрий aka Zzealot

template <typename T, typename FooType>
struct test
{
    int                        Foo(void)
    { return SpecFoo<FooType>(); }
private:
    template <typename U>
    int                        SpecFoo(void)
    { return 0; }
    template <>
    int                        SpecFoo<int>(void)
    { return 4; }
    template <>
    int                        SpecFoo<double>(void)
    { return 8; }
};

    test<bool, bool>        Test0;
    Test0.Foo();// 0
    test<bool, int>            Test1;
    Test0.Foo();// 4
    test<bool, double>        Test2;
    Test0.Foo();// 8
Мой компьютер прогоняет бесконечный цикл за 9 секунд, но, мне кажется, он мог бы сделать это быстрее...
Re[2]: Можно сделать частичную специализацию членов шаблона
От: Faust Россия  
Дата: 20.12.09 23:47
Оценка:
    test<bool, bool>        Test0;
    Test0.Foo();// 0
    test<bool, int>            Test1;
    Test1.Foo();// 4
    test<bool, double>        Test2;
    Test2.Foo();// 8
Мой компьютер прогоняет бесконечный цикл за 9 секунд, но, мне кажется, он мог бы сделать это быстрее...
Re: Можно сделать частичную специализацию членов шаблона кла
От: Юрий Жмеренецкий ICQ 380412032
Дата: 21.12.09 04:11
Оценка:
Здравствуйте, Zzealot, Вы писали:

Z>Вопрос такой — есть ли какой-то способ при создании специализации шаблона класса (полной или частичной — неважно) описывать (definition) не все члены класса, а только те, которые меняются по отношению к первичному шаблону ?


При создании специализации шаблона класса — нет, члены primary template не имеют отношения к членам специализаций.

14.5.4/3
Each class template partial specialization is a distinct template


14.5.4.3/1
A class template specialization is a distinct template. The members of the class template partial specialization are unrelated to the members of the primary template. ... the definitions of members of the primary template are never used as definitions for members of a class template partial specialization.


14.7.3/5
The definition of an explicitly specialized class is unrelated to the definition of a generated specialization. That is, its members need not have the same names, types, etc. as the members of the a generated specialization.


Z>Смотрел примеры в книгах — класс переписывают целиком — это ведь куча лишней работы ! А если мне требуется специализировать (модифицировать) только один из десяти методов класса ?


Если требуется, в ограниченных можно специализировать члены primary template (или специализаций, но наборы членов не будут пересекаться):

template<class T>
struct A
{
    int f()
    {
        return 0;
    }
};

template<>
int A<int>::f()
{
    return 1;
}

template<>
int A<char>::f()
{
    return 2;
}

//...

A<void> a1;
A<int>  a2;
A<char> a3;

int a = a1.f(); // 0
int b = a2.f(); // 1
int c = a3.f(); // 2


Для большей гибкости можно использовать traits или CRTP.

Z>В стандарте ISO 14882-2003 (действующий стандарт С++) в разделе 14.7.3 (Explicit specialization) описывается синтаксис специализации отдельных членов класса:


Z>template<class T1> class A {

Z>template<class T2> class B {
Z>template<class T3> void mf1(T3);
Z>void mf2();
Z>};
Z>};

Z>template<> template<class X>

Z>class A<int>::B { };
Z>template<> template<> template<class T>
Z>void A<int>::B<double>::mf1(T t) { } //
Z>// Здесь компайлер выдает ошибку: error C2039: 'mf1' : is not a member of 'A<T1>::B<X>'

Там ошибка. Должно быть так

template <class T1> class A 
{
    template<class T2> class B 
    {
        template<class T3> void mf1(T3);
        void mf2();
    };
};

template <> 
    template <class X>
    class A<int>::B 
    {
        template <class T> void mf1(T); // <- добавлено 
    };

template <> 
    template <> 
        template<class T>
        void A<int>::B<double>::mf1(T t) 
        {}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.