Я грав auto
у std::pair
. У наведеному нижче коді функція f
повинна повертати а std::pair
типів, які залежать від параметра шаблону.
Робочий приклад:
ПРИКЛАД 1
template <unsigned S>
auto f()
{
if constexpr (S == 1)
return std::pair{1, 2}; // pair of ints
else if constexpr (S == 2)
return std::pair{1.0, 2.0}; // pair of doubles
else
return std::pair{0.0f, 0.0f}; // pair of floats
}
Це працює з gcc 9.2, gcc 10.0, clang 9.0 та clang 10.0.
Далі, я хотів би чітко записати тип повернення як std::pair
чіткість:
ПРИКЛАД 2
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return {1, 2};
/* ... */
}
Як gcc 9.2 / 10.0, так і clang 9.0 / 10.0 не вдалося скомпілювати це.
gcc 9.2
error: invalid use of 'auto'
error: template argument 1 is invalid // first argument (auto) of std::pair
error: template argument 2 is invalid // second argument (auto) of std::pair
error: cannot convert '<brace-enclosed initializer list>' to 'int' in return
З останнього повідомлення про помилку, gcc 9.2, здається, вважає, що std::pair<auto, auto>
це int
. Як це можна пояснити?
gcc 10,0
error: returning initializer list
Ця помилка зрозуміла, однак я очікував, що конструктор std::pair
буде викликаний, чи щось тут мені не вистачає?
кланг 9.0 і 10.0
'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'
Гаразд, Кланг нічого з цього не любить. З другого повідомлення про помилку, схоже, що Кланг також вважає тип повернення int
.
Нарешті, щоб виправити помилку, отриману при компілюванні з gcc 10.0, я вирішив повернути std::pair
явно:
ПРИКЛАД 3
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return std::pair{1, 2};
/* ... */
}
кланг 9.0 і 10.0
Те саме, що раніше, але з додатковим:
no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'
Тут Кланг все ще думає, що ми повертаємось int
?
gcc 9.2
Те саме, що і раніше.
gcc 10,0
Це працює!
Я припускаю, що деякі функції все ж таки мають бути реалізовані, або в одній із ситуацій, описаних вище, чи є компілятор, який правильний, а інший неправильний? На мою думку, приклад 2 повинен працювати. Або не слід?