2016-05-02 2 views
3

Я борюсь со следующей ситуацией.вызовы функций в аргументах шаблона

#include "systemc.h" 

template<int maxval> 
class Foo { 
    /* Error: calls to constructors and functions cannot be part of a constant expression */ 
    sc_uint<int(log2(double(maxval)))> a; 
    ... 
}; 

int main() { 

    Foo<10> foo; 
    ... 
    return 0; 
} 

Как вы можете видеть выше, шаблонный шаблон Foo имеет параметр шаблона «maxval». «Foo» также содержит член, снова шаблонный класс, который использует параметр шаблона «maxval» вместе с функцией «log2» в своих аргументах шаблона для создания экземпляра. Однако изображенный код не будет работать, например, вызовы функций не могут быть частью постоянных выражений. Вы видите какую-либо возможность оценить, например. log2 (maxval) во время компиляции и использовать результат для дальнейших аргументов шаблона внутри 'Foo'?

Благодарим за помощь. (Я использую GCC 4.1.2)

ответ

8

Шаблоны ожидают значения времени компиляции. Для работы этой функции log2 должно быть constexpr (а это не так).

Вам нужно будет определить свою собственную функцию constexpr. В случае функции логарифм по основанию 2 может работать, если вам нужно целое число (отрезав точечную часть плавающей):

constexpr int log2(int number, int acc = 0) { 
    return number <= 1 ? acc : log2(number/2, acc + 1); 
} 

Edit:

я не заметил, что вопрос попросил GCC 4.1, который не поддерживает constexpr. Хотя вы должны попытаться обновиться, если этот параметр вам доступен, вы также можете найти решение на основе шаблонов, как это предлагается в ответе @ Флориана.

Edit 2:

В случае, если вы не хотите, чтобы полагаться на Boost,, вот простой шаблон на основе реализации вы можете использовать:

template<int V> 
struct log2 { 
    static int const value = 1 + log2<V/2>::value; 
}; 

template<> 
struct log2<0> {}; 

template<> 
struct log2<1> { 
    static int const value = 0; 
}; 

Тогда вы будете использовать это как log2<13>::value, что приведет к 3.

Еще одно редактирование:

constexpr реализация выше будет возвращать 0 для 0 и отрицательных чисел, что является ошибкой. Логарифм не определен для нуля или отрицательных значений (в действительной области), так что функция может быть скорректирована, чтобы бросить ошибку (так как это становится немного нечитаемым, я добавил некоторые разрывы строк для форматирования):

constexpr int log2(int number, int acc = 0) { 
    return number <= 0 
     ? throw std::logic_error{"Logarithm of zero or negative number not allowed."} 
     : number == 1 
      ? acc 
      : log2(number/2, acc + 1); 
} 
+1

GCC 4.1 намного старше, чем поддержка constexpr. –

+0

Хороший момент, извините, не заметил этого. Вам нужно либо обновить свой компилятор (что вам обязательно нужно сделать, если у вас есть опция, потому что 4.1 очень старый и не поддерживает много новых функций), либо используйте решение @ Florian. Я обновлю ответ, чтобы это отразить. –

+0

@ Stjepan: Большое спасибо за ваши предложения! Я думаю, что мне нужно пойти с шаблоном, поскольку «constexpr» не работает для меня, даже с GCC5.2.0 – chessat2002

Смежные вопросы