Как получить доступ к параметрам шаблона из производного класса?

у меня есть

template <int N> class Base

а также

class Derived : public Base<1>

... есть ли способ получить доступ к int N изнутри определения Derived::myMethod() (вместо получения ошибки компилятора «использование необъявленного идентификатора 'N'»)?

Точнее, я хотел бы сделать

void Derived::myMethod() {
   for (int n=0; n<N; n++) { ...

person PhilippJS    schedule 08.08.2012    source источник
comment
Почему бы вам просто не написать 1 вместо N? Что ты пытаешься сделать?   -  person Luchian Grigore    schedule 09.08.2012
comment
Кажется странным вопросом, потому что вы знаете, что N равно 1.   -  person jahhaj    schedule 09.08.2012
comment
Верно, я знаю, что N==1. Но у меня будет много вхождений 1 в Derived::myMethod(), и я хотел бы думать, что есть более разумный способ изменить значение N во время разработки, чем вручную обновлять все 1 до какого-то нового значения.   -  person PhilippJS    schedule 09.08.2012


Ответы (3)


Аргумент шаблона имеет область действия шаблона, но вы можете определить в шаблоне вложенную константу, которая может использоваться производными классами:

template <int N> class Base {
public: // or protected:
   static const int theN = N;
};
person David Rodríguez - dribeas    schedule 08.08.2012
comment
+1 за креативность, но если ему это нужно, я думаю, это скорее проблема дизайна... - person Luchian Grigore; 09.08.2012
comment
Я предполагаю, что это это проблема дизайна. Я предполагаю, что он создал шаблонный контейнер и использует от него наследование (вместо композиции), в то же время пытаясь получить доступ к контейнеру через какой-то защищенный, а не общедоступный интерфейс. Но мой хрустальный шар может быть выключен ... - person David Rodríguez - dribeas; 09.08.2012
comment
Ненавижу, когда мой хрустальный шар выключен... :( - person Luchian Grigore; 09.08.2012
comment
@David: +1 спасибо, это сработает. Однако это не то, что я ожидал - может ли это вообще не выделять память для этой дополнительной константы хотя бы один раз (даже если это статическая переменная, если только она не будет оптимизирована)? Также, на более стилистической ноте, теперь у меня дублируется доступ к этому значению (как через N, так и через N), что не очень минималистично. - person PhilippJS; 09.08.2012
comment
@David+Luchian: Конечно, это может быть проблема дизайна ... но я пытаюсь добиться следующего: у меня есть класс шаблона, который специализируется на ряде устройств захвата, и теперь я хочу получить класс, который реализует специальные операции для случая N=1. Однако этот производный класс не является просто специализацией шаблона для N=1. - person PhilippJS; 09.08.2012
comment
@PhilippJS: если вы не предоставите определение для статической константы, то пространство не будет потрачено впустую, это также означает, что если вы используете odr, вы получите ошибка компоновщика, поскольку переменная не определена. В качестве альтернативы вы можете использовать enum для этого. Наконец, если это специализация только для 1, то зачем она вам? - person David Rodríguez - dribeas; 09.08.2012
comment
@David: спасибо за ссылку на использование odr ... узнал что-то новое. enum также было бы решением, но он страдает от той же проблемы со стилем, что и подход static const: он загромождает область действия Base дополнительными символами. Наконец, почему? Потому что Base‹1› содержит пару четко определенных (иначе полезных) методов, которые я не хочу нигде переопределять, но один из них — myMethod() — нуждается в повторной реализации, очень (прикладно) специфичной для Derived, и который, таким образом, должен нельзя делать по специализации Base<1>::myMethod(). - person PhilippJS; 09.08.2012

Еще один вариант: вы можете создать шаблон производного класса:

template <int N>
class Derived : public Base<N>
{
    void myMethod()
    {
        for (int i = 0; i < N; ++i)
        //
    }
};
person Jesse Good    schedule 08.08.2012
comment
Да, но не будет никакого использования Derived‹N› для N!=1… когда-либо… поэтому для пользователей Derived (а также раскрытия деталей реализации) будет чрезмерным бременем указывать ‹1› каждый раз. время, когда они создают экземпляр. - person PhilippJS; 09.08.2012
comment
Вот как я бы это сделал (если бы мне в конечном итоге по какой-то причине понадобилось использовать параметр шаблона таким образом. Мне кажется странным, что N вообще шаблонен. Вам действительно нужно иметь экземпляр для каждого значения N (Похоже, это может привести к серьезному раздуванию кода). @PhilippJS Почему 1 вообще требуется для шаблона, учитывая ваш комментарий к ответу Джесси. Не может ли это быть член, инициализированный при построении? См. Мой ответ ниже... - person clanmjc; 09.08.2012
comment
@clanmjc: Как я объяснил в комментарии выше, Base‹N› представляет собой набор N устройств захвата. Для Derived у меня есть только одно — но очень специфическое — устройство захвата, которое требует особого отношения в myMethod(). У меня есть копипаст кода из Base<N>::myMethod() в Derived::myMethod(), но я хотел бы, чтобы структурные изменения были минимальными, чтобы избежать ошибок. Помните, что элемент инициализируется при построении (наверное, из Derived) - опять же, мне пришлось бы жестко закодировать Derived::myN(1) в списке инициализаторов элементов, не так ли? - person PhilippJS; 09.08.2012
comment
Смотрите мой ответ ниже о жестком кодировании. Кроме того, является ли N буквально целым числом или N неким объектом. Как бы вы ни нарезали его, в том числе и в вашем примере, где-то будет 1 хардкод. Однако это не означает, что классу Dervied нужно что-то знать об этой детали. - person clanmjc; 09.08.2012

Вот что я имел в виду из своего комментария выше:

class Base{
  public:
     Base(int value = 1) : value_(value){}  //don't need to use default param but can
  private:
     int value_
}

class Derived : public Base
{}

Зачем шаблонизировать N? Вам нужно специализировать весь класс? Альтернативой может быть «виртуализация» функций, не являющихся членами, которые вызываются из шаблона на основе критериев, установленных вами как «специализация».

Изменить: Частичная специализация метода в шаблоне класс

person clanmjc    schedule 08.08.2012