Почему мой шаблон не принимает список инициализаторов - PullRequest
23 голосов
/ 21 января 2011

Я создал шаблон следующим образом

template<typename T>
void f(T const& t) { }

Я хотел, чтобы он мог вызываться как контейнерами, так и списками инициализаторов.Я думал, что это будет initializer_list<int>, когда вызывается следующим образом.

f({1, 2, 3});

Но GCC ведет себя так, как будто он не соответствует стандартам

m.cpp: In function 'int main()':
m.cpp:6:25: warning: deducing 'const T' as 'const std::initializer_list<int>'
m.cpp:4:6: warning:   in call to 'void f(const T&) [with T = std::initializer_list<int>]'
m.cpp:6:25: warning:   (you can disable this with -fno-deduce-init-list)

Может кто-нибудь объяснить, как я могу сделать эту работубез предупреждений?Спасибо!

Ответы [ 3 ]

26 голосов
/ 21 января 2011

"вещь", такая как {1,2,3}, не может быть выражена как выражение. У него нет типа. Следовательно, вычитание типа не производится. Но C ++ 0x делает явное исключение для 'auto', поэтому

auto x = {1,2,3};

на самом деле работает и decltype (x) будет initializer_list<int>. Но это специальное правило, которое применяется только к авто. Я думаю, они хотели сделать такие петли

for (int x : {2,3,5,7,11}) {
   ...
}

работает, так как этот тип цикла использует специальное правило.

Что касается решения проблемы, вы можете добавить перегрузку initializer_list<T> в качестве «оболочки»:

template<class T>
inline void outer(initializer_list<T> il) {
   inner(il);
}

Я не проверял это, но в настоящее время я понимаю, что это должно работать.

3 голосов
/ 21 января 2011

Ну, документация говорит, что

Эта опция присутствует, потому что этот вывод является расширением текущей спецификации в рабочем проекте C ++ 0x, и существует некоторая обеспокоенность по поводу потенциальных проблем с разрешением перегрузки.

Эта информация может просто устареть (в зависимости от источника, который последний раз обновлялся в 2008 году). Насколько я понимаю, вычет был включен в GCC, но с ожиданием, что более поздняя версия стандарта уберет правило или, по крайней мере, ограничит его.

1 голос
/ 21 января 2011

Может кто-нибудь объяснить, как я могу сделать эту работу без предупреждений?

Я не знаю, относится ли this к точному коду, который вы цитировали, или если вы просто хотите узнать, как можно создать экземпляр шаблона функции со списком инициализаторов, не вызывая предупреждений, но если это последний и если проблема заключается только в выводе правильного типа, вы можете избежать этого, просто вызвав

f<initializer_list<int>>({1, 2, 3});

Это не красиво, но оно может избежать предупреждения, не используя аргументы командной строки компилятора.

Я бы, вероятно, разместил рядом комментарий, объясняющий, что вы не полагаетесь на то, что компилятор определяет правильный тип из-за недостатков в некоторых версиях GCC.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...