Нетипичный параметр шаблона - PullRequest
3 голосов
/ 10 марта 2011

У меня проблемы с нетиповым (переменная типа int) параметром шаблона.
Почему я не могу передать постоянную переменную int в функцию и позволить функции создать экземпляр шаблона?

template<int size>
class MyTemplate
{
  // do something with size
};

void run(const int j)
{
  MyTemplate<j> b; // not fine
}
void main()
{
  const int i = 3;
  MyTemplate<i> a; // fine;
  run(i); // not fine
}

не в порядке: компилятор говорит, ошибка: 'j' не может появляться в константном выражении

  • EDIT

Это то, что я закончилс.Может быть, кто-то может использовать его, кто-то может предложить лучший способ.

enum PRE_SIZE
{
    PRE_SIZE_256 = 256,
    PRE_SIZE_512 = 512,  
    PRE_SIZE_1024 = 1024,
};

template<int size>
    class SizedPool : public Singleton< SizedPool<size> >
{
public:
    SizedPool()
        : mPool(size)
    {
    }
    void* Malloc()
    {
        return mPool.malloc();
    }

    void Free(void* memoryPtr)
    {
        mPool.free(memoryPtr);
    }

private:
    boost::pool<>       mPool;
};

template<int size>
    void* SizedPoolMalloc()
    {
        return SizedPool<size>::GetInstance()->Malloc();
    }

template<int size>
    void SizedPoolFree(void* memoryPtr)
    {
        SizedPool<size>::GetInstance()->Free(memoryPtr);
    }

void* SizedPoolMalloc(int size)
{
    if (size <= PRE_SIZE_256)
        return SizedPoolMalloc<PRE_SIZE_256>();
    else if (size <= PRE_SIZE_512)
        return SizedPoolMalloc<PRE_SIZE_512>();
}


void toRun(const int j)
{
    SizedPoolMalloc(j);
}
void Test17()
{
    const int i = 3;
    toRun(i);
}

Ответы [ 3 ]

10 голосов
/ 10 марта 2011

Потому что нетипичные параметры шаблона требуют значений во время компиляции. Помните, что шаблоны - это механизм времени компиляции; шаблоны не существуют в конечном исполняемом файле. Также помните, что функции и передача аргументов функциям являются механизмами времени выполнения. Значение параметра j в run() не будет известно до тех пор, пока программа не запустится и не вызовет функцию run(), прошедшую после этапа компиляции.

void run(const int j)
{
    // The compiler can't know what j is until the program actually runs!
    MyTemplate<j> b;
}

const int i = 3;
run(i);

Именно поэтому компилятор говорит, что «j» не может появляться в константном выражении ».

С другой стороны, это нормально, потому что значение i известно во время компиляции.

const int i = 3;
// The compiler knows i has the value 3 at this point,
// so we can actually compile this.
MyTemplate<i> a;

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

Однако вы можете сделать так, чтобы ваша функция run() принимала параметр шаблона нетипичного типа так же, как ваш шаблонный класс MyTemplate принимает параметр шаблона нетипичного типа:

template<int j>
void run()
{
    MyTemplate<j> b;
}

const int i = 3;
run<i>();
2 голосов
/ 10 марта 2011

В основном C ++ имеет два вида констант:

const int a = 5;
MyTemplate<a> foo; // OK

const int b = rand();
MyTemplate<b> foo; // Not OK.

Первый пример - константа времени компиляции. В стандарте C ++ это интегральное выражение константы (ICE). Второй пример - постоянная времени выполнения. Он имеет тот же тип C ++ (const int), но это не ICE.

Ваша функция void run(const int j) является постоянной времени выполнения. Вы даже можете передать пользовательский ввод. Поэтому это недопустимый аргумент шаблона.

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

1 голос
/ 10 марта 2011

Потому что j должно быть известно во время компиляции.В вашем примере это не так.

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