Шаблоны параметров без типов. Почему глобальный и эталонный?

template<typename Body>
Body solve(Body a, Body b){
    Body zero(0);
    return zero;  
}

template<typename Body, Body& zero>
Body solve(Body a, Body b){
    return zero;
}

complex<double> zero(0);

int main() {
    complex<double> c1(1,2);
    complex<double> c2(3,4);    
    solve<complex<double>, zero_complex> (c1,c2);
    return 0;
}

Привет, я скомпилировал приведенный выше код, и все в порядке (здесь я опустил подробности). Теперь я заметил, что zero должна быть глобальной переменной и, кроме того, шаблоны должны получать zero по ссылке. В противном случае это вызывает ошибку компиляции. Я использую С++11.

Пожалуйста, объясните мне, почему это должно быть:

  1. пройти по ссылке
  2. глобальная переменная

Заранее спасибо.


person user5468942    schedule 26.10.2015    source источник
comment
Похоже, что некоторые детали отсутствуют, но, похоже, связаны с ссылочным параметром/аргументом, не являющимся типом. полезный.   -  person Shafik Yaghmour    schedule 26.10.2015
comment
@ShafikYaghmour, я думаю, довольно ясно, что здесь происходит.   -  person SergeyA    schedule 26.10.2015


Ответы (2)


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

Расположение состояния, которое они потребляют, становится частью их типа (или имени) и должно определяться во время компиляции/связывания/загрузки.

Локальные переменные (в стеке) имеют другое расположение — не постоянное. Местоположение не может быть определено во время компиляции/связывания/загрузки.

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

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

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

Распространенным методом является замена констант функторами без состояния. Таким образом, вы передаете «функтор тела» вместо константы тела.

Функтор не имеет состояния и имеет const operator(), который возвращает Body.

person Yakk - Adam Nevraumont    schedule 26.10.2015
comment
Спасибо. Только вы ответили на мой вопрос. :) - person user5468942; 27.10.2015

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

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

template<typename Body>
Body solve(Body a, Body b){
    Body zero(0);
    return zero;  
 }
template<typename Body, Body* zero>
   Body* solve(Body a, Body b){
   return zero;
}

int i = 0;
int main() {
  solve<int, &i>(10, 20);
}
person SergeyA    schedule 26.10.2015