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 по ссылке. В противном случае это вызывает ошибку компиляции. Я использую c ++ 11.

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

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

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

0
user5468942 26 Окт 2015 в 22:27

2 ответа

Лучший ответ

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

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

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

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

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

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

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

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

2
Yakk - Adam Nevraumont 26 Окт 2015 в 20:49

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

Другие аргументы шаблона, не относящиеся к типу, которые вы можете использовать, - это указатели и целочисленные типы, такие как 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);
}
1
SergeyA 26 Окт 2015 в 19:42