Gcc ошибка? Он необъяснимо разлагает массив на указатель, в то время как clang не

Это упрощенная версия, которая иллюстрирует проблему:

struct Foo {
    Foo() = default;

    template <std::size_t N>
    Foo(const char(&)[N]) {}
};

template <std::size_t N>
auto foo(const char (&arr)[N]) -> Foo
{
    return arr;
}

auto main() -> int
{
    foo("Stack Overflow");
}

g++, кажется, распадается на arr до const char *, хотя аргумент ссылки массива передается в ссылочный параметр массива. Он дает эту ошибку:

В экземпляре Foo foo(const char (&)[N]) [with long unsigned int N = 4ul]:

ошибка: не удалось преобразовать (const char*)arr из const char* в Foo

 return arr;
        ^

Пока clang++ ведет себя так, как я ожидаю и компилирует код.

Код компилируется в gcc с любой из этих модификаций:

return {arr};
return Foo(arr);
return (Foo)arr;
return static_cast<Foo>(arr);

Это ошибка gcc?

Пробовал это с all g++ и версиями clang++, которые поддерживают c++14. (*)

(*) Я просто попробовал его с моментальным снимком gcc 6, и он компилирует ОК. Так что это выглядит как ошибка, зафиксированная в gcc 6

Ответы

Ответ 1

Да, это было ошибкой в ​​GCC, где массивы преждевременно распадались бы на указатели, и конструктор преобразования больше не казался бы жизнеспособным кандидатом. Примеры, похожие на ваши (и возможное исправление), можно найти в комментариях этих двух отчетов об ошибках: