Выбор между созданием шаблона с аргументами указателя - PullRequest
5 голосов
/ 28 марта 2011

Посмотрите на следующий тестовый код:

template<class T> struct Wrap {};

template<typename T> inline
void fun (T *&Int)          // **choice 1**
{}

template<typename T> inline
void fun (Wrap<T> *&Int)    // **choice 2**
{}

int main()
{
  int i = 6;
  fun((char*&)(i));         // **call 1**
  fun((Wrap<char>*&)(i));   // **call 2**
}

Когда я запускаю этот код в linux g ++, он работает в соответствии с ожиданиями. Когда fun () вызывается с char * &, она вызывает функцию выбора 1 прямо вперед. Однако мне интересно, когда мы вызываем fun () с Wrap * &, и он вызывает вариант 2. Даже если варианты 1 и 2 кажутся действительными для второго вызова, компилятору удается выбрать немного лучшего соперника -> вариант 2 (потому что он существует).

Вопрос : Гарантируется ли, что такое же поведение будет сохранено для любого другого компилятора для C ++? Если нет, то есть ли другая альтернатива, чтобы сделать его детерминированным?

Ответы [ 4 ]

6 голосов
/ 28 марта 2011

Второй вариант выбран потому, что он более специализирован, чем первый, то есть T*& может связываться с любым временным T*, но Wrap<T>*& может связываться только с временным Wrap<T>*.Насколько я знаю, это Стандарт, и он должен быть переносимым, но то, что есть и не переносимо на практике, когда дело доходит до такого рода вещей, часто не является определением того, что такое Стандарт.

3 голосов
/ 28 марта 2011

Кто-то, кто лучше знает спецификацию, может это подтвердить, но я считаю, что, поскольку Wrap<T> является более конкретным типом, чем просто T, вызов 2 всегда будет разрешать вариант 2 на всех компиляторах платформ.

2 голосов
/ 28 марта 2011

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

Компилятор выполнит поиск вызова fun( (Wrap<char>*&) i ) с обычными механизмами поиска, найдет два шаблона и определит, что существуют две потенциальные перегрузки:

template <typename T> void fun( T*& );      // with T == Wrap<char>
template <typename T> void fun( Wrap<T>*& ) // with T == char

Разрешение перегрузки определит, что второе лучше соответствует, и создаст его экземпляр.Это гарантируется стандартом, но будьте осторожны: это не один и тот же шаблон, а скорее разные шаблоны, и вы можете столкнуться с неожиданными результатами.Посмотрите на статью @LiKao, на которую есть ссылки, чтобы узнать больше.

1 голос
/ 28 марта 2011

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

Херб Саттер: «Почему бы не специализировать шаблоны функций?»

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