Вызов функции, перегруженной в нескольких пространствах имен, из одного пространства имен


У меня есть следующий фрагмент кода:

void foo(double a) {}

namespace bar_space
{
  struct Bar {};

  void foo(Bar a) {}
}

Foo (double) - это общая функция из библиотеки. У меня есть собственное пространство имен bar_space с моей собственной структурой Bar. Я хотел бы реализовать перегрузку foo () для Bar, тем самым делая Bar более похожим на встроенные типы.

Проблема возникает, когда я пытаюсь вызвать исходный foo (double) из пространства имен:

namespace bar_space
{
  void baz()
  {
    foo(5.0); // error: conversion from ‘double’ to non-scalar type ‘ssc::bar_space::Bar’ requested
  }
}

Это не удается скомпилировать на gcc как на моей Fedora, так и на Mac.

Вызов

foo(5.0)

Из-за пределов пространства имен или с помощью

namespace bar_space
{
  ::foo(5.0)
}

Работает нормально, но это не делает мою новую функцию такой красивой, как я надеялся (другие разработчики также работают внутри bar_space).

Скрывает ли bar_space исходную функцию? Есть ли способ сделать foo(5.0) вызываемым из bar_space без явной области видимости (::)? Любая помощь ценится.

3 6

3 ответа:

В языке C++ существует понятие, называемое скрытие имени. В принципе, функция или имя класса "скрыты", если есть функция/класс с тем же именем во вложенной области. Это не позволяет компилятору "увидеть" скрытое имя.

Раздел 3.3.7 стандарта C++ гласит:

Имя может быть скрыто явным объявление того же имени в a вложенная декларативная область или производная класс (10.2)

Итак, чтобы ответить на ваш вопрос: в ваш пример void foo(double a); является скрытым от void bar_space::foo(Bar a);, поэтому вам нужно использовать оператор :: для вызова внешней функции.

Да, bar_space скрывает исходную функцию, и нет, вы не можете сделать foo(5.0) вызываемым из whithin bar_space без явного определения области , если foo(double) определен в глобальном пространстве имен.

Однако в вашем примере кода Вы можете использовать что-то вроде этого

namespace bar_space 
{
    using ::foo;
    void baz()
    {
       Bar bar;
       foo(5.0);
       foo(bar);
    }
}