Нетипичные параметры шаблона - PullRequest
77 голосов
/ 16 апреля 2011

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

template <std::string temp>
void foo()
{
     // ...
}
error C2993: 'std::string' : illegal type for non-type template parameter 'temp'.

Я понимаю, что такое постоянное интегральное выражение. Каковы причины запрета использования неконстантных типов, таких как std::string, как в приведенном выше фрагменте?

Ответы [ 4 ]

109 голосов
/ 16 апреля 2011

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

Вот что стандарт допускает для параметров шаблона нетипичного типа (14.1 [temp.param] p4):

Параметр шаблона нетипичного типа должен иметь одно из следующих значений ((необязательно, cv-qualified) типы:

  • целочисленный тип или тип перечисления,
  • указатель на объект или указатель на функцию,
  • lvalue ссылка на объект или lvalue ссылка на функцию,
  • указатель на элемент,
  • std::nullptr_t.
65 голосов
/ 16 апреля 2011

Это не разрешено.

Однако это разрешено:

template <std::string * temp> //pointer to object
void f();

template <std::string & temp> //reference to object
void g();

См. §14.1 / 6,7,8 в C ++ Standard (2003).


Иллюстрация:

template <std::string * temp> //pointer to object
void f()
{
   cout << *temp << endl;
}

template <std::string & temp> //reference to object
void g()
{
     cout << temp << endl;
     temp += "...appended some string";
}

std::string s; //must not be local as it must have external linkage!

int main() {
        s = "can assign values locally";
        f<&s>();
        g<s>();
        cout << s << endl;
        return 0;
}

Выход:

can assign values locally
can assign values locally
can assign values locally...appended some string
24 голосов
/ 16 апреля 2011

Вы должны иметь возможность манипулировать аргументами шаблона

template <std::string temp>
void f() {
 // ...
}

f<"foo">();
f<"bar">(); // different function!?

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

Планируется рассмотреть возможность использования типов литеральных классов в качестве типов параметров шаблона для post-C ++ 0x, которые инициализируются константными выражениями. Они могут быть искажены путем рекурсивного искажения элементов данных в соответствии с их значениями (например, для базовых классов мы можем применить обход в глубину слева направо). Но это точно не сработает для произвольных классов.

8 голосов
/ 16 апреля 2011

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

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

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

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