Подтвердить что ты не робот

Вложенные шаблоны

Имея мозговой пердеть... Можно ли сделать что-то подобное этой работе?

template<int a> struct Foo
{
    template<int b> struct Bar;
};

template<int a> struct Foo<a>::Bar<1> //Trying to specialize Bar
{
};

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

Предложения оценены!

P.S.: Я забыл упомянуть, что явно специализированный для Bar в области Foo не поддерживается языком. AFAICS, во всяком случае.

4b9b3361

Ответ 1

Да, вы можете. Но вам нужно будет изменить структуру вызова, но немного.

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

Это разрешено до тех пор, пока класс стратегии не вложен (и, следовательно, не зависит от типа неспециализированного шаблона).

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

template <class T>
class OuterThingThatIsNotSpecialized
{
  template <class U>
  void memberWeWantToSpecialize(const U& someObj_)
  {
    SpecializedStrategy<U>::doStuff(someObj_);
  }
};

template <class U>
struct SpecializedStrategy;

template <>
SpecializedStrategy<int>
{
  void doStuff(const int&)
  {
    // int impl
  } 
};

template <>
SpecializedStrategy<SomeOtherType>
{
  void doStuff(const SomeOtherType&)
  {
    // SOT impl
  } 
};

Это невероятно полезно, потому что вызовы OuterThingThatIsNotSpecialized для типов, где нет реализации, просто не скомпилируются.

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

Ответ 2

В разделе 18, раздел 14.7.3 стандарта 1998 года (ISO14882: 1998) говорится, что явная специализация (внутренних) классов элементов шаблона не допускается, когда (внешний) шаблонный класс не является явно специализированным.

Ответ 3

В соответствии с этими сообщениями:

http://www.cpptalk.net/template-member-function-specialization-vt11666.html

вы не можете специализировать членов шаблона класса шаблона, не специализируясь на внешнем классе. Они не цитируют стихи и главу. Моя копия "Язык программирования на С++" ничего не обнаруживает сразу, и моя копия стандарта находится дома (моя резервная копия, более известная здесь как "Крис", тоже не вокруг: -)

Ответ 4

Вот то, что я делал, что, по-моему, проще/больше связано с тем, что вы пытаетесь сделать:

С помощником

template<int a> struct Foo
{
    template<int, int> struct Bar__;
    template<int b> using Bar = Bar__<b, b>;
};

template<int a> template<int b, int c> struct Foo<a>::Bar__
{
    // general case
    const static int x = 0;
};
template<int a> template<int b> struct Foo<a>::Bar__<b, 1>
{
    const static int x = 1;
};

int main(int argc, const char * argv[]) 
{   
    std::cout << Foo<1>::Bar<0>::x << "\r\n"; // general case - output 0
    std::cout << Foo<1>::Bar<1>::x << "\r\n"; // specialized case - output 1
    return 0;
}

ИЛИ - Помощник может быть удален, если вы не возражаете удваивать специализацию каждый раз:

Без помощника

template<int a> struct Foo
{
    template<int b, int c> struct Bar;
};

template<int a> template<int b, int c> struct Foo<a>::Bar
{
    // general case
    const static int x = 0;
};
template<int a> template<int b> struct Foo<a>::Bar<b, 1>
{
    const static int x = 1;
};

int main(int argc, const char * argv[])
{   
    std::cout << Foo<1>::Bar<0, 0>::x << "\r\n"; // general case - output 0
    std::cout << Foo<1>::Bar<1, 1>::x << "\r\n"; // specialized case - output 1
    return 0;
}

Ответ 5

Вы не можете этого сделать. Я пробовал много вариантов. Это, однако, компилируется в GCC 4.1:

template<int a> struct Foo
{
    template<int b> struct Bar;
    template<1> struct Bar;
};

Изменить (после проверки стандарта): Однако, если дано, вы можете сделать это:

template <> template <> Foo<1> Bar<1>;

Но не если Foo не является первым специализированным.

Ответ 6

Как объяснили предыдущие плакаты, это невозможно. Однако вы можете перемещать вложенный шаблон в базовый класс без шаблона:

struct FooBase
{
    template<int b> struct Bar;
}
template<int a> struct Foo : public FooBase
{
};

struct FooBase::Bar<1> // specializing Bar
{
};

Ответ 7

Как указывали другие, С++ не позволяет вам специализировать вложенный класс, если шаблон внешнего класса также не специализирован. Когда у меня была такая ситуация, я смог обойти ее со вспомогательным классом, спрятанным во внутреннем пространстве имен:

namespace internal {
  template <int a, int b> struct FooBarHelper
  { /* ... */ };
  // Specialization
  template <int a> struct FooBarHelper<a, 1>
  { /* specialized version goes here */ };
}

template<int a> struct Foo
{
  template<int b> struct Bar : public internal::FooBarHelper<a, b>;
};

Конечно, это не так скрыто, как вам может понравиться.