2010-09-03 6 views
3

Я не могу получить это для компиляции вообще. Возможно, я не могу, но я не знаю, почему этого не должно быть.Объявление экземпляра явной специализации шаблона в регулярном классе

class A { 
    template <typename T> 
    class B { 
    int test() { return 0; } 
    }; 
    //template <> class B<int>; <-with this, namepace error 
    B<int> myB_; 
}; 

template <> class A::B<int> { 
    int test() { 
    return 1; 
    } 
}; 

Как представляется, компилятор жалуется на «Явная специализация„класса A :: B“должен быть объявлен до его использования.» Если я попытаюсь предоставить объявление froward в комментариях, компилятор жалуется «Явная специализация« B »должна быть объявлена ​​в пространстве имен, содержащем шаблон». Здесь мы используем 2 разных компилятора. Эта ошибка связана с компилятором IBM x1 в AIX, но при компиляции на наших системах Sun я получаю подобные ошибки с разными вариантами. Похоже на уловку-22.

Очевидно, что это очень надуманный, упрощенный пример, но он представляет проблему. Я хочу определить класс шаблона внутри класса, потому что класс шаблона относится только к содержащемуся классу. Не должно быть доступа к шаблону вне класса.

Я что-то упустил?

+0

Используйте четыре пробела для ввода кода (или выберите код и нажмите Ctrl + K). –

+0

Это не должно компилироваться, поскольку мы видим это даже без специализаций. Но это потому, что были удалены сайтом, запутывающим их с помощью HTML-тегов. Пожалуйста, выберите разделы кода и отметьте их как таковые, используя кнопку панели инструментов «101010» при публикации - это будет сохранять код в точности так, как есть. В противном случае специализация вне содержащего класса в порядке в соответствии со стандартом. Но, пожалуйста, восстановите недостающие части кода, чтобы обсуждение было эффективным. – usta

+0

В ситуации, когда у вас есть с myB_, вы можете использовать идиом PIMPL, чтобы не требовать B в этот момент. – usta

ответ

3

Вы верны. Это невозможно сделать (насколько я знаю). Объявление вашего участника вызывает неявное создание экземпляра до объявления явной специализации. Но как бы вы хотели заявить об этом? Вы не можете сделать это в классе. Другие считают, что this is an ugly restriction.

Вы можете обойти это, сделав указатель класса указателем. Для этого не требуется неявно создавать экземпляр класса в этой точке, а скорее в том месте, где вы создаете объект в конце. Я понимаю, что это уродливая работа. Поэтому лучше найти другие способы сделать это.

Например, частичные специализации разрешены в классе. Таким образом, вы можете добавить параметр шаблона шаблона, тогда вы можете выделить его в классе перед объявлением участника. Точно так же я нахожу это уродливым, но это не мешает мне так много, я чувствую.

0

Вы можете обойти эту проблему с помощью безымянного пространства имен для обеспечения конфиденциальности:

namespace { 

    template <typename T> 
    class B { 
    int test() { return 0; } 
    }; 

    template <> class B<int> { 
    int test() { 
     return 1; 
    } 
}; 

} 

class A { 
    B<int> myB_; 
}; 

Это будет компилировать, но если A должен быть виден за пределами этой единицы компиляции, вы будете нуждаться в более сложные механизмы (например, интерфейс и заводская установка или Pimpl).

0

B не является шаблоном и вы пытаетесь его спланировать. Это и есть причина ошибки. Вы можете проверить эти две ошибки C2913 и C3413. Вы ищите это?

class A 
{ 
    template<class T> 
    class B 
    { 
     inline int test() 
     { 
     return 0; 
     } 
    }; 
    A::B<int> myB_; 
}; 
+0

Извините, понял, что это не то, о чем просил пользователь user438938. Непонятно. – Gangadhar