Нестандартные параметры шаблона

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

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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

См. §14.1/6,7,8 в Стандарте С++ (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

Ответ 3

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

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

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

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

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

Ответ 4

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

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

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