Явное использование - PullRequest
       23

Явное использование

1 голос
/ 16 сентября 2010

Это было мотивировано этой статьей (стр. 5)

template<class T> 
T const &f(T const &a, T const &b){
    return (a > b ? a : b);
}

template int const &f<int>(int const &, int const &);

int main(){
    int x = 0, y = 0;
    short s = 0;
    f(x, y);     // OK
    f(x, s);     // Is this call well-formed?
}

Хорошо ли сформирован звонок 'f(x, s)'? Я предположил, что, поскольку шаблон функции 'f' явно создан, будут применены стандартные преобразования и, следовательно, 'short s' будет преобразован в 'int', чтобы соответствовать вызову явной специализации 'f<int>'. Но похоже, что это плохо сформировано?

В какой части стандарта говорится о применимых правилах в этом контексте?

Ответы [ 3 ]

5 голосов
/ 16 сентября 2010

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

Применимое правило содержится в спецификации процесса разрешения перегрузки в 13.3.1:

В каждом случае, когда кандидат является шаблоном функции, специализации кандидата на шаблон функции генерируются с использованием вывода аргумента шаблона (14.8.3, 14.8.2). Затем эти кандидаты обрабатываются как функции-кандидаты обычным способом.

14.8.3 / 1 также имеет значение:

Для каждого шаблона функции, если вывод и проверка аргумента завершаются успешно, аргументы шаблона (выводимые и / или явные) используются для создания экземпляра специализации одного шаблона функции, который добавляется к набору функций-кандидатов, которые будут использоваться для разрешения перегрузки. Если для данного шаблона функции вывод аргумента завершается неудачно, такая функция не добавляется в набор функций-кандидатов для этого шаблона.

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

3 голосов
/ 16 сентября 2010

Вызов f(x, s) синтаксически правильно сформирован, но компилятор не сможет вывести из него параметр шаблона T, потому что это может быть int или short (из-за первого и второгоаргументы).Создание шаблона не помогает, это только указывает на то, что компилятор скомпилирует эту специализацию и добавит ее в сгенерированный объектный файл.

Если вы хотите, чтобы вызов автоматически приводил s к int, используйте f<int>(x, s).

1 голос
/ 16 сентября 2010

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

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

Вот мое обновленное min:

#include <type_traits>

template< typename A, typename B >
typename std::common_type< A, B >::type // cannot return ref
my_min( A const &a, B const &b ) {
    return a < b? a : b;
}

 // enable_if< is_same< A, B > > the old, return-by-reference impl

int main() {
    int q = my_min( short(5), long(3) );
}
...