2015-05-11 5 views
4

Я пытаюсь использовать std :: initializer_list в качестве аргумента в функции, использующей зависящий от аргумента поиск (ADL). Но я не работаю, и я не понимаю, почему. Ниже приведен пример минимального отказа:initializer_list и зависимый от аргумента поиск

#include <initializer_list> 
    #include <iostream> 

    class Foo { 
    public: 
     inline friend void bar(std::initializer_list<Foo> v) { 
     std::cout << "size = " << v.size() << std::endl; 
     } 
    }; 

    void baz(std::initializer_list<Foo> v) { 
     std::cout << "size = " << v.size() << std::endl; 
    } 

    int main(){ 
     Foo a; 
     //bar({a,a}); // error: use of undeclared identifier 'bar' 
     baz({a,a}); // works 

     return 0; 
    } 

Как видно выше, эквивалентная глобальная функция работает нормально. Почему вышеуказанное не работает?

Я использую clang для OS X 10.10.

+0

Вы определяете реализацию друга внутри класса. Он должен быть снаружи, см. [This] (http://stackoverflow.com/a/7785963/2297365). Вот [рабочий пример] (http://coliru.stacked-crooked.com/a/b8fd514c67458c99). – huu

+0

@huu: Это не связано, если вы перемещаете тип и функции в пространство имен, вы заметите, что ADL их не найдет, независимо от того, определена ли функция внутри или вне класса. –

+0

'template std :: initializer_list il (std :: initializer_list x) {return x;} ' это несколько опасное обходное решение. 'bar (il ({a, a}))' работает. Опасно, потому что жизненные проблемы резервного массива. – Yakk

ответ

8

Я считаю, что проблема заключается в том, что подвыражения { a, a } действительно не имеет тип, и как таковой он не ассоциировали типов или пространств имен, которые в свою очередь, означает, что ADL не пинать. Если у вас есть функции в глобальном пространстве имен, нормальный поиск найдет его, и он найдет, что { a, a } может соответствовать вызову функции в качестве инициализатора для std::initializer_list<Foo>.

Синтаксис { a, a } называется приготовился-INIT-лист и это на самом деле не является выражением (или подвыражения) на языке.

+3

В качестве примечания есть исключение для 'auto', где выведено' std :: initializer_list'. 'auto param = {a, a}; bar (param), 'работает. –

+0

Хороший ответ! Я принял это. Спасибо! – Joel

2

Когда компилятор видит bar({a,a}), он не знает тип аргументов, поэтому он ищет bar в глобальном пространстве имен (::), и нигде больше. Если вы изменили эту строку на Foo{a,a}, то она знает, что аргумент равен Foo, а также ищет класс Foo для функций.

 Смежные вопросы

  • Нет связанных вопросов^_^