Я играл с 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'
Хорошо, Clang не нравится ничего из этого. Из второго сообщения об ошибке кажется, что Clang также считает, что тип возвращаемого значения 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'
Здесь Clang все еще думает, что мы возвращаемся int
?
GCC 9,2
Так же, как и раньше.
gcc 10.0
Оно работает!
Я предполагаю, что некоторые функции все еще должны быть реализованы, или в одной из ситуаций, описанных выше, есть ли компилятор, который является правильным, а другой неправильным? На мой взгляд, пример 2 должен работать. Или нет?
auto x = {1, 2};
работ, но только если все типы одинаковы.int
. Это не то, чтоint
заполнитель в сообщениях об ошибках; компилятор действительно думает, что этоint
. (Чтобы сделать это более понятным, gcc, вероятно, должен был в какой-то момент сказать «предполагая int».)std::pair __f{1,2};
работает.std::optional f() { return 4; }
работать.