Определение специализации шаблона в анонимном пространстве имен (и ошибка компиляции C2888) - PullRequest
0 голосов
/ 18 марта 2020

Версия в двух словах: Почему я не могу определить специализацию шаблона (типа std-lib), которая полезна только в текущем модуле компиляции в анонимном пространстве имен внутри этого модуля модуля / cpp ?

Более длинная версия:

У меня есть тип, который является быстрым помощником только внутри одного cpp файла, назовем его struct Helper. Поскольку он используется только в этом модуле компиляции, он объявлен и определен в анонимном пространстве имен внутри cpp.

Поскольку я хочу std::unordered_set<Helper>, я должен специализироваться std::hash. Когда я сейчас пытаюсь определить его в том же анонимном пространстве имен, я получаю C2888 'std::hash<'anonymous-namespace'::Helper>': symbol cannot be defined within namespace 'anonymous-namespace'. Почему это так?

Я тоже пытался добавить using namespace std и подобные вещи в AN, но безрезультатно.

/* This doesn't work */

namespace
{
    struct Helper
    {
        int member1;
        bool member2;
    };

    using namespace std;
    template<>
    struct std::hash<Helper>
    {
        size_t operator()(const Helper& helper) const
        {
            return 12345; /* how it's really generated is irrelevant here */
        }
    };
}

Конечно, я могу просто вывести специализацию за пределы АН, и это работает. Я просто хочу понять, почему оно не , пока оно внутри него

/* This works, but why doesn't the other? */

namespace
{
    struct Helper
    {
        int member1;
        bool member2;
    };
}

template<>
struct std::hash<Helper>
{
    size_t operator()(const Helper& helper) const
    {
        return 12345; /* how it's really generated is irrelevant here */
    }
};

1 Ответ

1 голос
/ 18 марта 2020

Символ, принадлежащий пространству имен std, должен быть определен в пространстве имен, включающем std, что означает, что вам придется определить его в глобальном пространстве имен.

Вот пример из C2888 :

namespace M {
   namespace N {
      void f1();
      void f2();
   }

   void N::f1() {}   // OK: namspace M encloses N
}

namespace O {
   void M::N::f2() {}   // C2888 namespace O does not enclose M
}

[temp.expl.spec/9] из черновика C ++ 20:

Явная специализация шаблона находится в сфере действия пространство имен, в котором был определен шаблон. [Пример:

namespace N {
  template<class T> class X { /* ... */ };
  template<class T> class Y { /* ... */ };

  template<>
  class X<int> { /* ... */ };     // OK: specialization in same namespace

  template<>
  class Y<double>;                // forward-declare intent to specialize for double
}

template<>
class N::Y<double> { /* ... */ }; // OK: specialization in enclosing namespace

template<>
class N::Y<short> { /* ... */ };  // OK: specialization in enclosing namespace

- конец примера]

...