Частично специализирующая реализация функции-члена - PullRequest
3 голосов
/ 07 февраля 2011

В настоящее время я выполняю рефакторинг некоторого кода, который явно специализирует функцию-член шаблона класса с двумя параметрами шаблона.

template <class S, class T>
class Foo
{
  void bar();
};

template <class S, class T>
void Foo<S, T>::bar()
{ /* Generic stuff */ }

template <>
void Foo<SomeType, SomeType>::bar()
{ /* Some special function */ }

Теперь я добавил еще несколько параметров шаблона, поэтому класс теперь выглядит так:

template <class S, class EXTRA0, class T, class EXTRA1>
class Foo
{
  void bar();
};

Эти два дополнительных параметра просто добавляют typedefs в мой класс, поэтому функциональность во время выполнения действительно не меняется. Есть ли способ сохранить (теперь частично) специализированную реализацию бара? Я не могу понять синтаксис для этого, и у меня есть догадка, что это может быть невозможно.

Редактировать: Я ищу что-то вроде:

template <class EXTRA0, class EXTRA1>
void foo<SomeType, EXTRA0, Sometype, EXTRA1>::bar()
{
   /* specialized implementation */
}

который, похоже, не компилируется ..

Ответы [ 4 ]

3 голосов
/ 07 февраля 2011

Вы правы, это невозможно.

Что вы можете сделать, это создать шаблон класса вспомогательного члена внутри нового Foo и поместить в него специализированную функцию как функцию-член, не являющуюся шаблоном. Специализируйте вспомогательный класс вместо функции.

Другая альтернатива - превратить специализацию в не шаблонную перегрузку.

1 голос
/ 07 февраля 2011

Этого можно добиться, используя вместо этого специальную функцию:

#include <iostream>

typedef int SomeType;

template <class A, class B>
class BarFunctor {
public:
    void operator()() {
        std::cout << "generic" << std::endl;
    }
};

template <>
class BarFunctor<SomeType, SomeType> {
public:
    void operator()() {
        std::cout << "special" << std::endl;
    }
};

template <class S, class T, class EXTRA0, class EXTRA1>
class Foo {
public:
    void helloWorld() {
        std::cout << "hello world !" << std::endl;
    }

    void bar() {
        return _bar();
    }

private:
    BarFunctor<S, T> _bar;
};

int main() {

    Foo<char, char, char, char> gen;
    Foo<SomeType, SomeType, char, char> spe;
    gen.helloWorld();
    spe.helloWorld();
    gen.bar();
    spe.bar();
    return 0;
}
1 голос
/ 07 февраля 2011

Вы можете создать базовый класс, в котором вы можете определить всех своих членов, кроме bar (), а затем создать производные классы (один для общего назначения, другой для SomeType):

template <class S, class T>
class FooBase
{
       // All other members 
};

template <class S, class EXTRA0, class T, class EXTRA1>
class Foo:public FooBase<S,T>
{
public:
      void bar()
      {

      }
};

struct SomeType {};

template <class EXTRA0, class EXTRA1>
class Foo<SomeType,EXTRA0,SomeType,EXTRA1>:public FooBase<SomeType,SomeType>
{
public:
    void bar()
    {

    }
};

int main()
{
    Foo<SomeType,int,SomeType,int> b;
    b.bar();
}
1 голос
/ 07 февраля 2011

Я не думаю, что то, что вы хотите, так легко возможно. Что-то вроде этого:

template <class S, class EXTRA0, class T, class EXTRA1>
class FooBase
{
    void bar();
};

template <class S, class EXTRA0, class T, class EXTRA1>
void FooBase<S, EXTRA0, T, EXTRA1>::bar()
{ /* Generic stuff */ }

template <class S, class EXTRA0, class T, class EXTRA1>
class Foo
    : public FooBase <S, EXTRA0, T, EXTRA1>
{ };

template <class EXTRA0, class EXTRA1>
class Foo<int, EXTRA0, int, EXTRA1>
    : public FooBase <int, EXTRA0, int, EXTRA1>
{
    void bar ();
};

template <class EXTRA0, class EXTRA1>
void Foo<int, EXTRA0, int, EXTRA1>::bar()
{ /* Some special function */ }
...