Переопределение стандартных функций
Я хотел бы переопределить поведение функции std, скажем, std::time. Можно ли вызвать std:: time и маршрутизировать ли это через мою пользовательскую функцию?
5 ответов
std
Вообще говоря, пространство имен запрещено. Добавление новых функций, перегрузок, классов или чего-либо еще в std
Пространство имен - ** неопределенное поведение *.
Единственным исключением являются шаблонные специализации. Вы можете предоставить специализации функций в std
Пространство имен. Функция, где это часто делается, std::swap
,
Это звучит как очень плохая идея. Вроде как переопределение true
или же false
, Лучше было бы написать собственную функцию-оболочку, скажем tim_time()
, который может или не может позвонить std::time()
внутренне.
Вместо того, чтобы называть это std::time
, перенаправьте все вызовы, которые вы можете иногда переопределять, через другое пространство имен.
namespace mystd{
using namespace std;
void time() { ... }
}
// ...
mystd::time(); // not std::time
mystd::copy(...); // calls std::copy, unless you override it like time()
Тогда призыв к mystd::time
вызовет модифицированную версию функции. Если вы вызываете не переопределенную функцию, например, mystd::copy
, он будет правильно преобразован в исходную функцию std.
На некоторых платформах вы можете это осуществить. В исходном коде определите функцию, т.е.
extern "C" time_t time(time_t *value)
{
...
}
Если вам повезет, компоновщик свяжет вашу версию std::time
более плотно, чем тот из стандартной библиотеки. Конечно, нет гарантии, что это сработает или будет связано так, как вы хотите. И как недостаток, у вас больше нет доступа к оригиналу std::time
,
Как и все остальные, это не переносимое поведение. Я уверен, что это работает на Linux. Я также уверен, что это не работает в Windows (компоновщик жалуется на конфликт).
Не переносимо. Понимая, что стандарт не определяет, что происходит, вы обычно можете определять любые символы и функции, которые вам нравятся, в пространстве имен std, или ссылаться на библиотеку, которая определяет эти символы, или что угодно. Это просто неопределенное поведение. Так что все, что вы можете сделать - это пососать и посмотреть, и надеяться, что это не сломается в следующей версии вашего компилятора.
Тем не менее, с большинством компиляторов это, вероятно, будет работать в основном при условии, что вы избежите столкновения правил одного определения с "настоящим" std::time. Это связано с тем, что большинство компиляторов на самом деле не делают ничего особенного с пространством имен std, а заголовочные файлы и библиотеки, которые они используют для его реализации, ничем не отличаются от заголовочных файлов и библиотек, которые вы можете написать сами.
Дима абсолютно прав, однако, что выход за рамки стандарта почти всегда является очень плохой идеей. Может быть, если вы застряли в каком-то отладочном аду, где вы в основном хотите добавить протоколирование в std::time, но не можете, тогда стоит подумать. Иначе не ходи туда. Если вы хотите протестировать некоторый код, чтобы увидеть, правильно ли он работает в разное время, передайте этому коду параметр (или параметр шаблона), указывающий, какую функцию времени он должен вызывать.