Что означает "type * = nullptr" - PullRequest
1 голос
/ 26 мая 2020

Не понимаю.

template<class T>
T foo2(T t, typename std::enable_if<std::is_integral<T>::value >::type* = nullptr) 
{
    return t;
}

type * = 0 ? Что это.

Ответы [ 2 ]

3 голосов
/ 26 мая 2020

Это способ достижения SFINAE : функция может быть выбрана только в том случае, если все типы могут быть заменены должным образом.

Если std::is_integral<T>::value равно false (т. Е. T не является целочисленным типом), std::enable_if<...> не будет иметь члена type, поэтому произойдет ошибка замены, и эта функция не будет вызываться (и может быть другая перегрузка).

Если T является целочисленным типом, то typename std::enable_if<std::is_integral<T>::value >::type будет void, поэтому второй параметр будет иметь тип void*. Это безымянный параметр со значением по умолчанию nullptr, поэтому вам не нужно его указывать.

Итак, вы бы назвали его так:

foo2(0);  // T is `int`, which is integral, so the function can be called
foo2(0, nullptr);  // Same as above, but explicitly passing the parameter

// Can't call the function, because `double` is not integral,
// so second type is a substitution failure
// foo2(0.0);

Обратите внимание, что это обычно может быть достигнуто либо с помощью параметра шаблона по умолчанию:

// Same `void*` if integral, else substitution failure
template<class T, typename std::enable_if<std::is_integral<T>::value >::type* = nullptr>
T foo2(T t)
{
    return t;
}

// Or alternatively with an `int` if integral, else substitution failure
template<class T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
T foo2(T t)
{
    return t;
}

, либо непосредственно в типе возвращаемого значения:

template<class T>
// Returns `T` if it's integral, else substitution failure
typename std::enable_if<std::is_integral<T>::value, T>::type foo2(T t)
{
    return t;
}

А в C ++ 20 вы можете использовать requires (или std::integral концепция в данном случае)

template<class T> requires std::is_integral_v<T>
T foo2(T t)
{
    return t;
}

template<std::integral T>
T foo2(T t)
{
    return t;
}
1 голос
/ 26 мая 2020

В C / C ++ вы можете в объявлении функции опускать имя (а) параметра (ов). Иногда это предпочтительный стиль при отделении интерфейса от реализации, чтобы избежать путаницы между именами параметров, скажем, прототипа функции и реализации. Я никогда раньше не видел, чтобы кто-то делал это. Но то, что они затем делают, как указал @IgorTandetnik, - это инициализировать этот «фиктивный параметр» значением по умолчанию.

...