вторник, 2 марта 2010 г.

Explicitly qualified name

Вчера наткнулся на интересную проблему. Рассмотрим следующий пример:
std::string convert();
// ...
namespace tools {
class Numeric {
// ...
friend std::string ::convert();
};
}
При компиляции этого кода компилятор выдает ошибку. Что тут не так и как исправить положение? Ответ и пояснение чуть позже.



Ошибка тут в том, что компилятор парсит этот код как std::string::convert, как правильно заметил ztonix в комментариях. К сожалению избавиться от :: нельзя, т.к. без точек мы декларируем функцию tools::convert и пометим её как friend.

Решением проблемы будет использовать скобки для выделения имени функции:
friend std::string (::convert)();
Стоит отметить, что со встроенными типами таких проблем нет. Компилятор однозначно воспринимает friend int ::convert();

5 комментариев:

  1. Проблема в том, что транслятор трактует строку `friend std::string ::convert()' как `friend std::string::convert()', что очеведно не то что было задумано. В голову приходит что-то типа такого решения (при условии, что существующий дизайн изменять нельзя и в пространстве имен `tools' также может оказаться объявление функции `std::string convert()'):

    std::string convert();
    // ...
    namespace tools {
        namespace global_decl {
            using ::convert;
        }
        class Numeric {
            // ...
            friend std::string global_decl::convert();
        };
    }

    ОтветитьУдалить
  2. Ошибка именно в этом, но дополнительное пространство вводить не хочется.

    ОтветитьУдалить
  3. Тогда вот так (хотя мне предыдущий способ больше нравится):

    std::string convert();
    // ...
    namespace tools {
        class Numeric {
            friend std::string const ::convert();
        };
    }

    ОтветитьУдалить
  4. Хотя вместо `const' возможно логичнее использовать `volatile', но это уже дело вкуса...

    ОтветитьУдалить
  5. const (как и volatile) нельзя писать, т.к. это уже получается другая функция.

    ОтветитьУдалить