Номера-тип параметров шаблона


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

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

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

4 70

4 ответа:

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

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

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

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

Это не допускается.

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

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

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

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

вы должны быть в состоянии калечить аргументы шаблона

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

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

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

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

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

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

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