Расширение метода C ++ - PullRequest
       40

Расширение метода C ++

4 голосов
/ 15 сентября 2008

Можете ли вы специализировать метод шаблона внутри класса шаблона, не специализируя параметр шаблона класса?

Обратите внимание, что специализация имеет значение параметра шаблона, а не его тип.

Это похоже на компиляцию в компиляторе Visual Studio 2008 SP1, но не в GCC 4.2.4.

#include <iostream>
using namespace std;
template <typename T>
class A
{
private:
    template <bool b>
    void testme();

    template <>
    void testme<true>() { cout << "true" << endl; };

    template <>
    void testme<false>() { cout << "false" << endl; };

public:
    void test();
};

template<typename T> struct select {};
template<> struct select<int>    { static const bool value = true; };
template<> struct select<double> { static const bool value = false; };

template <class T>
void A<T>::test() { testme<select<T>::value>(); }

int main(int argc, const char* argv[])
{
    A<int>      aInt;
    A<double>   aDouble;

    aInt.test();
    aDouble.test();

    return 0;
}

GCC сообщает мне: "ошибка: явная специализация в области, не связанной с пространством имен," класс A ""

Если он не поддерживается в стандарте, может кто-нибудь сказать мне, почему?

Ответы [ 4 ]

4 голосов
/ 15 сентября 2008

Это не поддерживается в стандарте (и это, очевидно, известная ошибка в Visual Studio, что вы можете сделать это).

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

template<typename ty>
class A
{
public:
      void foo(bool b);
      void foo(int i);
};

Эквивалентно:

template<typename ty>
class A
{
public:
   template<typename ty2>
   void foo(ty2);

   template<>
   void foo(bool b);

   template<>
   void foo(int i);
};
2 голосов
/ 09 ноября 2008

вот как вы это делаете:

template<typename A>
struct SomeTempl {
    template<bool C> typename enable_if<C>::type 
    SomeOtherTempl() {
        std::cout << "true!";
    }

    template<bool C> typename enable_if<!C>::type 
    SomeOtherTempl() {
        std::cout << "false!";
    }
};

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

1 голос
/ 16 сентября 2008

Вот еще один обходной путь, также полезный, когда вам нужно частично специализировать функцию (что недопустимо). Создайте класс функтора шаблона (т. Е. Класс, единственная цель которого - выполнить одну функцию-член, обычно называемую operator ()), специализировать ее и затем вызывать из вашей функции шаблона.

Мне кажется, я научился этому трюку у Херба Саттера, но не помню, какая это была книга (или статья). Для ваших нужд это, вероятно, излишне, но тем не менее ...

template <typename T>
struct select;

template <bool B>
struct testme_helper
{
  void operator()();
};

template <typename T>
class A
{
private:
  template <bool B> void testme()
  {
    testme_helper<B>()();
  }

public:
  void test()
  {
    testme<select<T>::value>();
  }
};

template<> void testme_helper<true>::operator()()
{
  std::cout << "true" << std::endl;
}

template<> void testme_helper<false>::operator()()
{
  std::cout << "false" << std::endl;
}
0 голосов
/ 15 сентября 2008

Я никогда не слышал о том, что это возможно; это будет иметь смысл для меня, если он будет не , поддерживаемый всеми компиляторами. Итак, вот идея для обхода проблемы:

Реализация шаблонной функции вне вашего класса, которая выполняет те же действия, что и метод. Затем вы можете специализировать эту функцию и вызывать ее из метода. Конечно, вам также придется передавать любые переменные-члены, которые ему нужны (и указатели на них, если вы хотите изменить их значения).

Вы также можете создать другой шаблонный класс в качестве подкласса и специализировать его, хотя я никогда сам этого не делал и не уверен на 100%, что он будет работать. (Пожалуйста, прокомментируйте, чтобы дополнить этот ответ, если вы знаете, сработает ли этот второй подход!)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...