2016-05-18 3 views
0

Обычно, если для нового типа требуется хэш, std::hash должен быть специализированным. Я написал тестовую хеширующую библиотеку и хотел бы использовать ее для всех типов, которые уже не были специализированы стандартной библиотекой.Повторное определение std :: hash template struct

Я пробовал следующее с gcc/4.9.3 и clang/3.7.0. К моему удивлению, это работает.

#include <utility> 
#include <functional> 
#include <iostream> 

namespace std { 

template<typename T> 
class hash 
{ 
    public: 
     size_t operator()(const T & obj) 
     { 
      return 99; 
     } 
}; 
} 

int main(void) 
{ 
    int i = 10; 
    std::pair<int, int> pi{22,33}; 

    std::hash<int> hi; 
    std::hash<std::pair<int, int>> hpi; 

    std::cout << "Hash of int: " << hi(i) << "\n"; 
    std::cout << "Hash of int pair: " << hpi(pi) << "\n"; 
    return 0; 
} 

Хэш целого числа является само целое число (которое является стандартной версии библиотеки) и хэш пары 99.

Так два вопроса.

  1. Почему это работает? шаблонная версия std::hash уже должна быть объявлена. (Мое единственное предположение, что это находится в более глубоком пространстве имен, которое отправляется)

  2. Является ли это стандартным поведением?

Edit: Ответ на вопрос 1 - template<typename T> struct hash объявлена, но, кажется, не быть определен в любом месте. Вот почему я могу это определить.

+3

Неопределенное поведение, как обычно, включает в себя «появление для работы». –

+0

@ T.C. Следовательно, желая знать, было ли это определено поведение или нет ... –

ответ

1

17.6.4.2.1 патезрасе [namespace.std]

1 Поведение C++ программе не определен, если оно добавляет декларации или определения для namespace std или к пространству имен в пределах namespace std если не указано иное . Программа может добавить специализацию шаблона для любого стандартного шаблона библиотеки до namespace std только в том случае, если объявление зависит от пользовательского типа, и специализация соответствует стандартным требованиям библиотеки библиотеки для исходного шаблона и не является явно запрещенным .

Поскольку вы переопределили общий шаблон, который уже существует до namespace std, у вас есть неопределенное поведение. И это включает в себя как @ T.C. упоминает в комментариях, что программа работает нормально.

+1

Моя первоначальная путаница была в том, что я думал, что я переопределяю что-то (что нарушит ODR и не будет компилироваться). Несмотря на то, что я действительно добавляю определение, оно по-прежнему нарушает это правило. (И да, я очень хорошо знаю, что неопределенное поведение может по-прежнему работать). –

Смежные вопросы