Предупреждение C ++: вывод _U1 как std :: initializer_list <int> - PullRequest
4 голосов
/ 09 ноября 2011

Я использую g++-4.6.1 --std=c++0x и получаю предупреждение, я не могу расшифровать этот бит кода:

#include <vector>
#include <tuple>

int main()
{
    std::tuple<std::vector<int>, int> t{ {1, 2, 3}, 10};
}

Я получаю следующее предупреждение:

scratch.cpp: In function ‘int main()’:
scratch.cpp:6:55: warning: deducing ‘_U1’ as ‘std::initializer_list<int>’ [enabled by default]
/usr/local/include/c++/4.6.1/tuple:329:9: warning:   in call to ‘std::tuple<_T1, _T2>::tuple(_U1&&, _U2&&) [with _U1 = std::initializer_list<int>, _U2 = int, _T1 = std::vector<int>, _T2 = int]’ [enabled by default]
scratch.cpp:6:55: warning:   (you can disable this with -fno-deduce-init-list) [enabled by default]

Глядя на реализацию:

template<typename _T1, typename _T2>
class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
    {
      typedef _Tuple_impl<0, _T1, _T2> _Inherited;

    public:
      //...

      template<typename _U1, typename _U2>
        explicit
        tuple(_U1&& __a1, _U2&& __a2)
        : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
    //...
}

Кажется, что он жалуется на то, что он перенаправляет с initializer_list<int> ({1, 2, 3} в моем коде) на std::vector<int>, который будет первым типом в std::tuple. Мне кажется, это нормально.

Итак, мой вопрос: что означает это предупреждение?

Ответы [ 2 ]

5 голосов
/ 09 ноября 2011

Это скорее предположение, чем цитата из стандарта, но я думаю, что это имеет некоторый смысл.

Проблема в том, что заключенный в фигурные скобки список может означать много вещей.Это может быть списком инициализаторов, но при равномерной инициализации это может быть также любое количество других вещей, таких как агрегатные инициализаторы или просто аргументы конструктора.

Рассмотрим следующую ситуацию:

struct Bar { Bar(int, int, int){} };

void foo(const std::vector<int> & v);
void zoo(const Bar & v);

Я могу позвонить как foo({1,2,3}), так и zoo({1,2,3}).Поскольку тип аргумента обеих функций известен, нет никакой двусмысленности.И все же аргумент foo выводится как список инициализатора, в то время как аргумент zoo является вызовом конструктора равномерной инициализации.

В ситуации кортежа проблема заключается в том, что все задействованные типы являются шаблонами.Тип аргумента конструктора должен быть выведен ;это не известно во время вызова функции.Его истинная роль становится очевидной только в функции body .

Поскольку существует множество способов создания члена кортежа, этот вывод может быть неоднозначным или просто неправильным, и поэтому компилятор предупреждаетВы, что оно делает предположение .

На самом деле, вы можете построить провал этого предположения очень просто:

std::tuple<Bar, std::vector<int>> s{{1,2,3}, {1,2,3}};

Это не даст построить первоечлен кортежа, потому что список скобок выводится неправильно.Единственный «хороший» способ написания кортежей - это явно:

std::tuple<Bar, std::vector<int>> s{Bar{1,2,3}, std::vector<int>{1,2,3}};
3 голосов
/ 09 ноября 2011

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

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