2016-07-18 2 views
2

Предположим, у меня есть шаблон класса Foo:Пусть шаблон частичных функций членов специализаций делиться с общими конкретизации

template<typename T, typename U> 
struct Foo { 
    ~Foo() = default; 

    // I want to reuse these methods for all instantiations of Foo 
    void bar() {} 
    void poi() {} 
}; 

Я хочу специализироваться деструктор для любого Foo<T, int>, но я хочу Foo<T, int> поделиться другие функции-члены с общие экземпляры. Но если я пытаюсь сделать:

template<typename T> 
Foo<T, int>::~Foo() 
{} 

вне класса, он не компилируется, то ошибка является «неправильным использованием неполного типа struct Foo<T, int>». Что означает эта ошибка, и как я могу достичь того, что я пытаюсь сделать?

+0

Почему вы не создать базовый класс от от которых наследуются как общие экземпляры, так и специализации? – linuxfever

ответ

-1

Если foo и poi делать вещи, которые зависят от параметров шаблона, то вы могли бы извлечь ваше специализированное поведение деструкторов в отдельный класс, например,

#include <iostream> 

template <typename T, typename U> 
struct Foo; 

template <typename T, typename U> 
struct FooDestructorTraits 
{ 
    static void destroy(Foo<T, U> * ptr) 
    { 
     std::cout << "default" << std::endl; 
    } 
}; 

template <typename U> 
struct FooDestructorTraits<int, U> 
{ 
    static void destroy(Foo<int, U> * ptr) 
    { 
     std::cout << "special" << std::endl; 
    } 
}; 

template <typename T, typename U> 
struct Foo 
{ 
    ~Foo() noexcept { FooDestructorTraits<T, U>::destroy(this); } 

    void bar() {} 
    void baz() {} 
}; 

int main() { 
    Foo<void, void> x; 
    Foo<int, void> y; 
} 
3

Это не представляется возможным частично специализировать (не templated) функция-член. Вам нужно специализироваться на всем классе.

Один из способов сделать то, что вы хотите, - наследовать общие функции.

template<typename T, typename U> struct MemberProvider 
{ 
     ~MemberProvider() = default; 

     void bar() {}; 
     void poi() {}; 
}; 


template<typename T, typename U> 
struct Foo : public MemberProvider<T, U> 
{ 
    ~Foo() = default; 

// Optionally, you can still do this. 
// However, note that these HIDE the inherited functions 

    void bar() {}; 
    void poi() {}; 
}; 

template<typename T> struct Foo<T, int> : public MemberProvider<T, int> 
{ 
    ~Foo() {}; 
}; 

Обратите внимание, что вам также необходимо будет включать в себя все члены, на которые действуют общие функции в унаследованном классе.

Однако я бы предложил, чтобы приведенное выше представляет собой запах кода. Если бы я видел код, подобный приведенному выше, в производственной среде, я бы рассматривал наличие дефекта дизайна. Имейте в виду, что при разрушении такого класса наиболее производный деструктор вызывается перед деструкторами базового класса. MemberProvider также не является полиморфным основанием.

3

Вы можете явно специализировать функции-члены шаблонов классов, но вы не можете частично их специализировать - это то, что вы пытаетесь сделать.

Если вам необходимо частично специализировать деструктор таким образом, что сохраняет общий вариант по умолчанию, вам придется частично специализировать шаблон всего класса:

template <class T, class U> 
struct FooCommon { 
    ~FooCommon() = default; 

    void bar() {} 
    void poi() {} 
}; 

template <class T, class U> 
struct Foo : FooCommon<T, U> { }; 

template <class T> 
struct Foo<T, int> : FooCommon<T, int> { 
    ~Foo() { 
     // special logic here 
    } 
}; 
Смежные вопросы