Почему ADL не работает с неназванным initializer_list? - PullRequest
3 голосов
/ 21 июня 2019

Рассмотрим следующий код. Здесь, если мы используем std::begin для неназванного initializer_list с явным std::, все работает нормально. Если мы опускаем std:: и используем begin для именованного initializer_list, это также работает нормально. Но если мы пропустим std:: и сделаем все остальное, как в первом случае, он не скомпилируется.

#include <iostream>
#include <iterator>
void func(int len, const int* x)
{
    for(int i=0;i<len;++i)
        std::cout << x[i] << "\n";
}
int main()
{
    {
        // OK
        func(5, std::begin({1,3,6,823,-35}));
    }
    {
        // OK
        auto&& list = {1,3,6,823,-35};
        func(5, begin(list));
    }
//  {
//      // Fails to compile
//      func(5, begin({1,3,6,823,-35}));
//  }
}

Я получаю следующую ошибку компиляции (после того, как я раскомментирую неисправный код):

test.cpp: In function ‘int main()’:
test.cpp:21:11: error: ‘begin’ was not declared in this scope
   func(5, begin({1,3,6,823,-35}));
           ^~~~~
test.cpp:21:11: note: suggested alternative:
In file included from /usr/include/c++/8/string:51,
                 from /usr/include/c++/8/bits/locale_classes.h:40,
                 from /usr/include/c++/8/bits/ios_base.h:41,
                 from /usr/include/c++/8/ios:42,
                 from /usr/include/c++/8/ostream:38,
                 from /usr/include/c++/8/iostream:39,
                 from test.cpp:1:
/usr/include/c++/8/bits/range_access.h:105:37: note:   ‘std::begin’
   template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
                                     ^~~~~

Почему ADL работает с именованным initializer_list (т.е. list в приведенном выше примере), но не работает с безымянным?

1 Ответ

5 голосов
/ 21 июня 2019

, но не с неназванным?

Нет, {1,3,6,823,-35} не является неназванным std::initializer_list.{1,3,6,823,-35} - это фигурный список инициализации .Даже его можно использовать для создания std::initializer_list в определенных контекстах, но это не сам std::initializer_list.Тогда ADL не будет работать для begin({1,3,6,823,-35}).

Список фигурных скобок не является выражением и, следовательно, не имеет типа, например, decltype({1,2}) не сформирован.

и

Специальное исключение сделано для вывода типа с использованием ключевого слова auto, которое выводит любой список фигурных скобок как std::initializer_list.

Вот почему работает второй случай;list выводится как std::initializer_list&&.

...