Пример трех запутанных шаблонов функций - PullRequest
0 голосов
/ 07 июня 2018
#include <iostream>

// maximum of two values of any type:
template<typename T>
T max (T a, T b)
{
    std::cout << "max<T>() \n";
    return b < a ? a : b;
}

// maximum of three values of any type:
template<typename T>
T max (T a, T b, T c)
{
    return max (max(a,b), c); // uses the template version even for ints
} //because the following declaration comes
// too late:

// maximum of two int values:
int max (int a, int b)
{
    std::cout << "max(int,int) \n";
    return b < a ? a : b;
}

int main()
{
    ::max(47,11,33); // OOPS: uses max<T>() instead of max(int,int)
}

В этом примере (из книги, отмеченной ниже) я не понял почему :: вызов max (47,11,33), как ожидается, будет использовать max (int, int) .Итак, один - это 2 аргумента, другой - 3 аргумента. Я думаю, что он использует определение функции 3 аргументов, как и должно быть.

Я что-то упустил?

Примечание: Дэвид Вандевурде, Николай М. Хосуттис, Дуглас ГрегорШаблоны C ++: Полное руководство [2-е изд.] Книга

Ответы [ 3 ]

0 голосов
/ 07 июня 2018

Решение: специализировать max<T> для T = int вместо определения int(int, int) функции:

#include <iostream>

template<typename T>
T max (T a, T b)
{
    std::cout << "max<T>() \n";
    return b < a ? a : b;
}

template<>
int max (int a, int b)
{
    std::cout << "max(int,int) \n";
    return b < a ? a : b;
}

template<typename T>
T max (T a, T b, T c)
{
    return max (max(a,b), c);
}

int main()
{
    ::max(47,11,33); // BINGO: uses specialized max<int>()
}

Вывод:

max(int,int) 
max(int,int) 

Это хрупкооднако, если не шаблонная функция будет использовать max<int> после определения max<T> и до того, как max<int> будет специализированным, в соответствии с [temp.expl.spec]/6 программа будет некорректной, неттребуется диагностика.

Если вы не можете пойти на такой риск, вам доступны инструменты.СФИНА является одним из них и может запретить генералу max<T> вызываться с T = int.Это может привести либо к работающей программе, либо к ошибке компиляции.

0 голосов
/ 07 июня 2018

::max(47, 11, 33); на самом деле ::max<int>(47, 11, 33);

, что в свою очередь вызовет ::max<int>(::max<int>(47, 11), 33);, что может быть удивительно.

Поскольку int является встроенным (так что ADL отсутствует), max(int, int) должно быть видно до того, как будет определено max(T, T, T), чтобы разрешить вызов этой версии в шаблоне:

С пользовательским типом, благодаря ADL, ваша max функция может быть объявлена ​​после:

template <typename T>
T max (T a, T b)
{
    std::cout << "max<T>()\n";
    return b < a ? a : b;
}

// Should be declared **before** max(T, T, T)
int max(int a, int b)
{
    std::cout << "max(int,int) \n";
    return b < a ? a : b;
}

template<typename T>
T max (T a, T b, T c)
{
    return max (max(a,b), c);
}

struct S {};

// Might be declared after max(T, T, T)
S max(S, S)
{
    std::cout << "max(S, S)\n";
    return {};
}

Теперь и max(0, 1, 2), и max(s, s, s) будут вызывать внутреннюю перегрузку без шаблона.

Demo

0 голосов
/ 07 июня 2018

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

max<T>(T a, T b, T c) знает о max<T>(T a, T b), но НЕ знает, что существует целочисленная перегрузка, потому что она объявлена ​​послеэто.

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