Подтвердить что ты не робот

С++ 11 член инициализации список неоднозначность

Я борюсь с тем, что кажется двусмысленностью в разрешении символа С++ 11 из-за реализации стандартной библиотеки GNU в этой среде:

  • Arch Linux 4.2.5-1 (x86_64)
  • g++ 5.2.0
  • clang++ 3.7.0

Пример:

#include <iostream>
#include <string>

struct version {

  unsigned major;
  unsigned minor;
  unsigned patch;

  version(unsigned major, unsigned minor, unsigned patch) :
    major(major), minor(minor), patch(patch) { }

  friend std::ostream & operator<<(std::ostream & out, version const& v) {
    out << v.major << ".";
    out << v.minor << ".";
    out << v.patch;
    return out;
  }

};

int main(int argc, char ** argv) {
  version v(1, 1, 0);
  std::cout << v << std::endl;
  return 0;
}

Ошибка компилятора:

error: member initializer 'gnu_dev_major' does not name a non-static data
  member or base class
error: member initializer 'gnu_dev_minor' does not name a non-static data
  member or base class

Команда:

clang++ -std=c++11 -o test *.cpp

Оператор разрешения области видимости не применим в списках инициализации членов, поэтому я не могу понять, как устранить эту неоднозначность. Этот образец компилируется без флага С++ 11.

4b9b3361

Ответ 1

Другой способ - использовать фигурные скобки:

version(unsigned major, unsigned minor, unsigned patch) :
  major{major}, minor{minor}, patch{patch} { }

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

Ответ 2

Из моей собственной попытки компиляции, похоже, glibc делает что-то глупое и #define с общими строчными словами.

Когда я добавляю следующее после #include s, оно компилируется.

#undef major
#undef minor

Ответ 3

Похоже, что major и minor - это макросы, определенные в sys/sysmacros.h, который вводится <iostream>, что проблематично, поскольку эти имена не зарезервированы для реализации. Обратите внимание, что если код будет уменьшен, и мы включим только sys/sysmacros.h, то будет возникать одна и та же проблема.

Когда я компилирую это с clang on Wandbox, я получаю эту более информативную ошибку, которая позволяет нам видеть, откуда идет конфликт:

 usr/include/x86_64-linux-gnu/sys/sysmacros.h:67:21: note: expanded from macro 'major'
 # define major(dev) gnu_dev_major (dev)
                     ^~~~~~~~~~~~~~~~~~~

 usr/include/x86_64-linux-gnu/sys/sysmacros.h:68:21: note: expanded from macro 'minor'
 # define minor(dev) gnu_dev_minor (dev)
                     ^~~~~~~~~~~~~~~~~~~

Мы можем найти это в следующем отчете об ошибке идентификатор основного макроса, расширенного в gnu_dev_major:

Проблема в том, что g++ добавляет -D_GNU_SOURCE, а major() - это макрос в _GNU_SOURCE (или _BSD_SOURCE или когда не задан набор функций).

Вы всегда можете #undef major после включения заголовков.

и

makedev(), major() и minor() должны быть функциями, а не макросами.

Похоже, что они были введены в GNUC >= 2 в sys/sysmacros.h для Обратная совместимость. Это не очень хорошая идея.

Смачивание макросами опасно, поскольку оно загрязняет пространство имен пользователей.

и поэтому мы можем видеть undef макросы - одно из решений, и, к сожалению, это рекомендуемое решение, так как это не исправляет ошибку:

Изменений не будет. Если какой-то код не нравится макросам, добавьте #undefs после соответствующего #include. Макросы являются частью API и их устранение только создают проблемы.

Мы могли бы использовать {} в intializer участника, но для этого требуются изменения типов параметров, поскольку они оставляют их, поскольку int будет сужающим преобразованием, которое не допускается. Конечно, изменение имен также является возможным решением.

Обновить

Я отправил отчет об ошибке glibc. Есть некоторые вопросы о том, действительно ли это gcc или ошибка glibc, детали скорее задействованы.

Ответ 4

/usr/include/sys/sysmacros.h имеет следующие макросы:

# define major(dev) gnu_dev_major (dev)
# define minor(dev) gnu_dev_minor (dev)
# define makedev(maj, min) gnu_dev_makedev (maj, min)

похоже, что вам нужно отменить его или использовать другие имена