Компилятор выбирает неправильный оператор < - PullRequest
3 голосов
/ 02 ноября 2011

У меня есть две библиотеки, одна из которых зависит от другой.Первая библиотека определяет некоторые перечисления и предоставляет оператор << (), который печатает короткий фрагмент текста для каждого перечисления.У меня есть модульные тесты, доказывающие, что это работает. </p>

Вторая библиотека, которая зависит от первой, передает значение перечисления в std :: cout (std :: ostringstream ведет себя так же) и получает соответствующее числовое значение довольночем текст.Шаблонный код не используется, так что это не проблема шаблона и перегрузки.Я просмотрел вывод препроцессора, чтобы убедиться, что правильные определения видны.Я использую g ++ 4.1.2.

Я не могу воспроизвести проблему за пределами моих библиотек (которые состоят из тысяч строк), поэтому я не могу опубликовать пример кода.Моя попытка создать пример кода также убеждает меня, что я понимаю, как это должно работать.Я предполагаю, что что-то, включенное в один из заголовков, заставляет компилятор сделать другой выбор при выборе оператора << для использования.</p>

Мой вопрос: Как я могу получить представление о том, какой выбор имеет компилятор при выборе версии используемого оператора и почему он выбрал стандартную вместо моей.

Редактировать : Добавление подписей в соответствии с запросом: Обратите внимание, что этот упрощенный пример не демонстрирует проблему.

Заголовок из первой библиотеки:

namespace utcp {
  enum GainType {AGC_GAIN_MODE, MAN_GAIN_MODE };
}

// I've tried this passing the argument by value as well.
inline std::ostream& operator<<(std::ostream &os, const hdr::GainType &val)
{...}

Код из второй библиотеки

std::cout << "Gain Text: " << hdr::AGC_GAIN_MODE << std::endl;

Ответы [ 3 ]

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

Проблема в том, что в одном из комментариев упоминается проблема зависимого поиска аргумента. Когда компилятор выполняет поиск для std::cout << my_enum_variable, он просматривает текущее пространство имен, пространство имен std и пространство имен, где определен тип my_enum_variable. Только если нет кандидата, он пойдет вверх и будет искать во вложенных пространствах имен. В этом случае, поскольку любой enum неявно преобразуется в int, он будет применять это преобразование, а не искать во вложенных пространствах имен. Директива using здесь не помогает.

Простое решение заключается в перемещении перегруженного operator<< в то же пространство имен, что и перечисление:

namespace utcp {
  enum GainType {AGC_GAIN_MODE, MAN_GAIN_MODE };
  inline std::ostream& operator<<(std::ostream &os, const GainType &val) {...}
}

Это должно позволить ADL определить вашу перегрузку.

2 голосов
/ 02 ноября 2011

Я рекомендую вам обновить хотя бы до g ++ 4.4, чтобы получить некоторые строго типизированные функции перечисления .

Я недавно обновился до 4.6 и изменил все свои перечисления на enum class - я считаю,Строгая типизация даст вам представление об ошибке в коде.

1 голос
/ 02 ноября 2011

Вы пытались явно привести ваш аргумент к <<?

...